-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Expand file tree
/
Copy pathDynamicProperty.swift
More file actions
78 lines (69 loc) · 2.81 KB
/
DynamicProperty.swift
File metadata and controls
78 lines (69 loc) · 2.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import Foundation
import ReactiveSwift
/// A typed mutable property view to a certain key path of an Objective-C object using
/// Key-Value Coding and Key-Value Observing.
///
/// Bindings towards a `DynamicProperty` would be directed to the underlying Objective-C
/// object, and would not be affected by the deinitialization of the `DynamicProperty`.
public final class DynamicProperty<Value>: MutablePropertyProtocol {
private weak var object: NSObject?
private let keyPath: String
private let cache: Property<Value>
private let transform: (Value) -> Any?
/// The current value of the property, as read and written using Key-Value
/// Coding.
public var value: Value {
get { return cache.value }
set { object?.setValue(transform(newValue), forKeyPath: keyPath) }
}
/// The lifetime of the property.
public var lifetime: Lifetime {
return object?.reactive.lifetime ?? .empty
}
/// The binding target of the property.
public var bindingTarget: BindingTarget<Value> {
return BindingTarget(lifetime: lifetime) { [weak object, keyPath] value in
object?.setValue(value, forKey: keyPath)
}
}
/// A producer that will create a Key-Value Observer for the given object,
/// send its initial value then all changes over time, and then complete
/// when the observed object has deallocated.
///
/// - important: This only works if the object given to init() is KVO-compliant.
/// Most UI controls are not!
public var producer: SignalProducer<Value, Never> {
return cache.producer
}
public var signal: Signal<Value, Never> {
return cache.signal
}
internal init(object: NSObject, keyPath: String, cache: Property<Value>, transform: @escaping (Value) -> Any?) {
self.object = object
self.keyPath = keyPath
self.cache = cache
self.transform = transform
}
/// Create a typed mutable view to the given key path of the given Objective-C object.
/// The generic type `Value` can be any Swift type, and will be bridged to Objective-C
/// via `Any`.
///
/// - parameters:
/// - object: The Objective-C object to be observed.
/// - keyPath: The key path to observe.
public convenience init(object: NSObject, keyPath: String) {
self.init(object: object, keyPath: keyPath, cache: Property(object: object, keyPath: keyPath), transform: { $0 })
}
}
extension DynamicProperty where Value: OptionalProtocol {
/// Create a typed mutable view to the given key path of the given Objective-C object.
/// The generic type `Value` can be any Swift type, and will be bridged to Objective-C
/// via `Any`.
///
/// - parameters:
/// - object: The Objective-C object to be observed.
/// - keyPath: The key path to observe.
public convenience init(object: NSObject, keyPath: String) {
self.init(object: object, keyPath: keyPath, cache: Property(object: object, keyPath: keyPath), transform: { $0.optional })
}
}