-
-
Save churabou/21dc2500fd8b7e6956e06abfe6e5d124 to your computer and use it in GitHub Desktop.
Swift4 KVO data binding
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@objcMembers class ViewModel: NSObject { | |
private (set) dynamic var count = 0 | |
private (set) dynamic var title: String? = "" | |
} | |
final class ViewController: UIViewController { | |
private var bag = DisposableBag() | |
private let viewModel = ViewModel() | |
private let countLabel = UILabel() | |
private let titleLabel = UILabel() | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
viewModel.subscribe(\.count) { [weak self] count in | |
self?.countLabel.text = "count: \(count)" | |
}.dispose(by: bag) | |
viewModel | |
.bind(\.title, to: titleLabel, at: \.text) | |
.dispose(by: bag) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol Bindable { } | |
extension NSObject: Bindable { } | |
extension Bindable where Self: NSObject { | |
func subscribe<Value>(_ keyPath: KeyPath<Self, Value>, changeHandler: @escaping (Value) -> ()) -> Disposable { | |
return observe(keyPath, options: [.initial, .new]) { _, change in | |
guard let newValue = change.newValue else { return } | |
changeHandler(newValue) | |
} | |
} | |
func bind<Target, Value>(_ fromKeyPath: KeyPath<Self, Value>, | |
to target: Target, | |
at targetKeyPath: ReferenceWritableKeyPath<Target, Value> | |
) -> Disposable { | |
return subscribe(fromKeyPath) { newValue in | |
target[keyPath: targetKeyPath] = newValue | |
} | |
} | |
} | |
protocol Disposable { | |
func dispose() | |
} | |
extension Disposable { | |
func dispose(by bag: DisposableBag) { | |
bag.append(self) | |
} | |
} | |
extension NSKeyValueObservation: Disposable {} | |
extension Disposable where Self: NSKeyValueObservation { | |
func dispose() { | |
invalidate() | |
} | |
} | |
final class DisposableBag { | |
private var disposables: [Disposable] = [] | |
func append(_ disposable: Disposable) { | |
disposables.append(disposable) | |
} | |
deinit { | |
disposables.forEach { $0.dispose() } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment