#13: KVO and KVC in Swift 3
Is using KVO and KVC still possible with Swift?
In fact it is, but your objects will need to have NSObject
as parent and you’ll need to mark as dynamic
all properties you plan to observe:
class MyClass: NSObject {
dynamic var variable = 0
dynamic var anotherVariable = 0
var dontObserveMe = 1
}
Let’s see an example for KVC, we’ll create an instance of the class above and set and get one of its properties using a key path:
var c = MyClass()
c.value(forKeyPath: #keyPath(MyClass.variable)) // 0
c.setValue(11, forKeyPath: #keyPath(MyClass.variable))
The only significant novelty here is the new #keyPath
expression introduced with SE-0062, that validates the keypath it contains, an extremely useful functionality.
For KVO, your observers will need to extend the NSObject
class too:
class MyObserver : NSObject{
var myContext: Int = 1
var value: MyClass
init(_ value: MyClass) {
self.value = value
super.init()
value.addObserver(self,
forKeyPath: #keyPath(MyClass.variable),
options: .new,
context: &myContext)
}
override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {
if context == &myContext {
print("Change at keyPath = \(keyPath) for \(object)")
}
}
deinit {
value.removeObserver(self, forKeyPath: #keyPath(MyClass.variable))
}
}
No significant changes here too, the API evolved following the new Swift 3 naming style.
We can easily verify that everything works:
var observed = MyClass()
var o = MyObserver(observed)
observed.variable = 42 //Change notification!
observed.anotherVariable = 0 //No notification.
Did you like this article? Let me know on Twitter or subscribe for updates!