Is key-value observation (KVO) available in Swift?

key-value observing swift 4 example
nskeyvalueobservation
swift combine kvo
swift kvo alternative
swift kvo protocol
swift observe value change
swift observe key-value coding
kvo and kvc in swift medium

If so, are there any key differences that weren't otherwise present when using key-value observation in Objective-C?

(Edited to add new info): consider whether using the Combine framework can help you accomplish what you wanted, rather than using KVO

Yes and no. KVO works on NSObject subclasses much as it always has. It does not work for classes that don't subclass NSObject. Swift does not (currently at least) have its own native observation system.

(See comments for how to expose other properties as ObjC so KVO works on them)

See the Apple Documentation for a full example.

Using Key-Value Observing in Swift, KVO, which stands for Key-Value Observing, is one of the techniques for observing the program state changes available in Objective-C and� Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects. You can use key-value observing with a Swift class, as long as the class inherits from the NSObject class. You can use these three steps to implement key-value observing in Swift.

You can use KVO in Swift, but only for dynamic properties of NSObject subclass. Consider that you wanted to observe the bar property of a Foo class. In Swift 4, specify bar as dynamic property in your NSObject subclass:

class Foo: NSObject {
    @objc dynamic var bar = 0
}

You can then register to observe changes to the bar property. In Swift 4 and Swift 3.2, this has been greatly simplified, as outlined in Using Key-Value Observing in Swift:

class MyObject {
    private var token: NSKeyValueObservation

    var objectToObserve = Foo()

    init() {
        token = objectToObserve.observe(\.bar) { [weak self] object, change in  // the `[weak self]` is to avoid strong reference cycle; obviously, if you don't reference `self` in the closure, then `[weak self]` is not needed
            print("bar property is now \(object.bar)")
        }
    }
}

Note, in Swift 4, we now have strong typing of keypaths using the backslash character (the \.bar is the keypath for the bar property of the object being observed). Also, because it's using the completion closure pattern, we don't have to manually remove observers (when the token falls out of scope, the observer is removed for us) nor do we have to worry about calling the super implementation if the key doesn't match. The closure is called only when this particular observer is invoked. For more information, see WWDC 2017 video, What's New in Foundation.

In Swift 3, to observe this, it's a bit more complicated, but very similar to what one does in Objective-C. Namely, you would implement observeValue(forKeyPath keyPath:, of object:, change:, context:) which (a) makes sure we're dealing with our context (and not something that our super instance had registered to observe); and then (b) either handle it or pass it on to the super implementation, as necessary. And make sure to remove yourself as an observer when appropriate. For example, you might remove the observer when it is deallocated:

In Swift 3:

class MyObject: NSObject {
    private var observerContext = 0

    var objectToObserve = Foo()

    override init() {
        super.init()

        objectToObserve.addObserver(self, forKeyPath: #keyPath(Foo.bar), options: [.new, .old], context: &observerContext)
    }

    deinit {
        objectToObserve.removeObserver(self, forKeyPath: #keyPath(Foo.bar), context: &observerContext)
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        guard context == &observerContext else {
            super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
            return
        }

        // do something upon notification of the observed object

        print("\(keyPath): \(change?[.newKey])")
    }

}

Note, you can only observe properties that can be represented in Objective-C. Thus, you cannot observe generics, Swift struct types, Swift enum types, etc.

For a discussion of the Swift 2 implementation, see my original answer, below.


Using the dynamic keyword to achieve KVO with NSObject subclasses is described in the Key-Value Observing section of the Adopting Cocoa Design Conventions chapter of the Using Swift with Cocoa and Objective-C guide:

Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects. You can use key-value observing with a Swift class, as long as the class inherits from the NSObject class. You can use these three steps to implement key-value observing in Swift.

  1. Add the dynamic modifier to any property you want to observe. For more information on dynamic, see Requiring Dynamic Dispatch.

    class MyObjectToObserve: NSObject {
        dynamic var myDate = NSDate()
        func updateDate() {
            myDate = NSDate()
        }
    }
    
  2. Create a global context variable.

    private var myContext = 0
    
  3. Add an observer for the key-path, and override the observeValueForKeyPath:ofObject:change:context: method, and remove the observer in deinit.

    class MyObserver: NSObject {
        var objectToObserve = MyObjectToObserve()
        override init() {
            super.init()
            objectToObserve.addObserver(self, forKeyPath: "myDate", options: .New, context: &myContext)
        }
    
        override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
            if context == &myContext {
                if let newValue = change?[NSKeyValueChangeNewKey] {
                    print("Date changed: \(newValue)")
                }
            } else {
                super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)
            }
        }
    
        deinit {
            objectToObserve.removeObserver(self, forKeyPath: "myDate", context: &myContext)
        }
    }
    

[Note, this KVO discussion has subsequently been removed from the Using Swift with Cocoa and Objective-C guide, which has been adapted for Swift 3, but it still works as outlined at the top of this answer.]


It's worth noting that Swift has its own native property observer system, but that's for a class specifying its own code that will be performed upon observation of its own properties. KVO, on the other hand, is designed to register to observe changes to some dynamic property of some other class.

Guide to KVO in Swift 5 with code examples, Key-value observing is the ability for Swift to attach code to variables, so that It's similar to property observers ( willSet and didSet ), except KVO is for Available from iOS 8.0 – learn more in my book Swift Design Patterns� Key-value observing is a Cocoa programming pattern you use to notify objects about changes to properties of other objects. It's useful for communicating changes between logically separated parts of your app—such as between models and views. You can only use key-value observing with classes that inherit from NSObject.

What is key-value observing?, Key-Value Observing, KVO for short, is an important concept of the Cocoa API. class inherits from NSObject , this method is available to us. KVO, which stands for Key-Value Observing, is one of the techniques for observing the program state changes available in Objective-C and Swift. The concept is simple: when we have an object with some instance variables, KVO allows other objects to establish surveillance on changes for any of those instance variables. KVO is a practical example of the Observer pattern. What makes Objective-C (and Obj-C bridged Swift) unique is that every instance variable that you add to the class becomes

An example might help a little here. If I have an instance model of class Model with attributes name and state I can observe those attributes with:

let options = NSKeyValueObservingOptions([.New, .Old, .Initial, .Prior])

model.addObserver(self, forKeyPath: "name", options: options, context: nil)
model.addObserver(self, forKeyPath: "state", options: options, context: nil)

Changes to these properties will trigger a call to:

override func observeValueForKeyPath(keyPath: String!,
    ofObject object: AnyObject!,
    change: NSDictionary!,
    context: CMutableVoidPointer) {

        println("CHANGE OBSERVED: \(change)")
}

Key-Value Observing (KVO) and Swift 3, Key-value coding is a mechanism for accessing an object's properties The objc attribute makes the declaration available in Objective-C, which is So to use KVC & KVO in swift, for the properties we want to observe in KVO� Key-value observing is the ability for Swift to attach code to variables, so that whenever the variable is changed the code runs. It’s similar to property observers ( willSet and didSet ), except KVO is for adding observers outside of the type definition. KVO isn’t terribly nice in pure Swift code, because it relies on the Objective-C runtime – you need to use @objc classes that inherit from NSObject, then mark each of your properties with @objc dynamic.

Yes.

KVO requires dynamic dispatch, so you simply need to add the dynamic modifier to a method, property, subscript, or initializer:

dynamic var foo = 0

The dynamic modifier ensures that references to the declaration will be dynamically dispatched and accessed through objc_msgSend.

KVO & KVC In swift, Key-Value Observing (KVO) is related directly to another powerful and important mechanism, named Key-Value Coding, or KVC. Actually, any� In the following example, the type User Info supports KVO for its last Login property, as described in Using Key-Value Observing in Swift.The view Did Load() method uses the observe(_: options: change Handler:) method to set up a closure that handles any change to the property.

Introduction to Key-Value Observing (KVO) in iOS, Use Key-Value Observing to get notified when properties of an object change. Registering for Key-Value Observing describes the full lifecycle of registering for, receiving, and de-registering for key value observation notifications. KVO’s primary benefit is that you don’t have to implement your own scheme to send notifications every time a property changes.

Observing properties with Key-Value Observering, KVO is a binding way in Objective-C. The observer is allowed to receive notifications when the observed object changes. Automatic key-value� Browse other questions tagged ios swift xcode key-value-observing or ask your own question. Is key-value observation (KVO) available in Swift? 925.

The replacement of KVO(Key-Value Observing) in Swift, Simple KVO example in Swift based on: http://stackoverflow.com/questions/ 24092285/is-key-value-observation-kvo-available-in-swift. KVO.swift. As you may have noticed, observation still lurks inside the confines of Cocoa's KVO mechanism, therefore it's only available to Obj-C classes and Swift classes inheriting NSObject (every Swift-dev's favorite type) with the added requirement that any value you intend to observe, must be marked as @objc (every Swift-dev's favorite attribute) and declared dynamic.

Comments
  • An example project that demonstrates KVO being used in a UIKit interface via Swift: github.com/jameswomack/kvo-in-swift
  • @JanDvorak See the KVO Programming Guide, which is a nice introduction to the topic.
  • Although not an answer to your question, you can also start actions using the didset() function.
  • Note there is a Swift4 bug when you use .initial. For a solution see here. I highly recommend to see Apple docs. It's been updated recently and covers lots of important notes. Also see Rob's other answer
  • Since Xcode 6 beta 5 you can use the dynamic keyword on any Swift class to enable KVO support.
  • Hooray for @fabb! For clarity, the dynamic keyword goes on the property that you want to make key-value-observable.
  • The explanation for the dynamic keyword can be find in the Apple Developer Library's Using Swift with Cocoa and Objective-C section.
  • Since this wasn't clear to me from @fabb's comment: use the dynamic keyword for any properties inside of a class you'd like to be KVO compliant (not the dynamic keyword on the class itself). This worked for me!
  • Not really; you can't register a new didSet from the "outside", it has to be part of that type at compile time.
  • What is the purpose of myContext and how do you observe multiple properties?
  • According to KVO Programming Guide: "When you register an object as an observer, you can also provide a context pointer. The context pointer is provided to the observer when observeValueForKeyPath:ofObject:change:context: is invoked. The context pointer can be a C pointer or an object reference. The context pointer can be used as a unique identifier to determine the change that is being observed, or to provide some other data to the observer."
  • you need to remove observer in deinit
  • @devth, as I understand, if subclass or superclass also registers KVO observer for the same variable, observeValueForKeyPath will be called multiple times. Context can be used to distinguish own notifications in this situation. More on this: dribin.org/dave/blog/archives/2008/09/24/proper_kvo_usage
  • If you leave options empty, it just means that the change won't include the old or new value (e.g. you might just get the new value yourself by referencing the object itself). If you just specify .new and not .old, it means that change will include only the new value, but not the old value (e.g. you often don't care about what the old value was, but only care about the new value). If you need observeValueForKeyPath to pass you both the old and new value, then specify [.new, .old]. Bottom line, options just specifies what is included in the change dictionary.