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

I'm also on Twitter and GitHub.

Subscribe via RSS or email.