#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.

This short post is one of the Swift Bites, click the link for more!


This is the blog of Umberto Raimondi, you can reach me at me@this domain.

I'm also on Twitter and GitHub.

Subscribe via RSS or email.