Skip to content

Instantly share code, notes, and snippets.

@thelbane
Created June 12, 2017 18:52
Show Gist options
  • Save thelbane/7c32e8d4438b6f9fde7ae30678ada11f to your computer and use it in GitHub Desktop.
Save thelbane/7c32e8d4438b6f9fde7ae30678ada11f to your computer and use it in GitHub Desktop.
KVOChangeNotifier
import Foundation
class KVOChangeNotifier: NSObject {
weak var object: AnyObject?
let keyPaths: [String]
var dependentObject: AnyObject
let dependentKeyPaths: [String]
init(object: AnyObject, keyPaths: [String], dependentObject: AnyObject, dependentKeyPaths: [String]) {
self.object = object
self.keyPaths = keyPaths
self.dependentObject = dependentObject
self.dependentKeyPaths = dependentKeyPaths
super.init()
dependentKeyPaths.forEach {
dependentObject.addObserver(self, forKeyPath: $0, options: [.initial,.new,.prior], context: nil)
}
}
deinit {
dependentKeyPaths.forEach {
dependentObject.removeObserver(self, forKeyPath: $0)
}
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
let isPrior = change?[.notificationIsPriorKey] as? Bool ?? false
if isPrior {
keyPaths.forEach {
self.object?.willChangeValue(forKey: $0)
}
} else {
keyPaths.reversed().forEach {
self.object?.didChangeValue(forKey: $0)
}
}
}
}
@thelbane
Copy link
Author

thelbane commented Oct 13, 2017

This helper enables computed properties to emit KVO change notifications when their dependencies change.

e.g.:

fullNameNotifier = KVOChangeNotifier(self, [#keyPath(ViewModel.fullName)], person, [#keyPath(Person.firstName), #keyPath(Person.lastName)])

addObserver(self, forKeyPath: #keyPath(ViewModel.fullName), options: [.new, .initial], context: nil)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment