30. January 2018

Observing properties with Key-Value Observering

The Objective-C object model supports observing properties - registering for a notification that gets sent when a property of an object changes. This can also be used from Swift.

Caveat: Only types that can be represented in Objective-C can be observed. So no structs, no generic types and enums need to be derived from Int. It works nicely though for Swift Arrays and dictionaries.

To observe a property, you need to subclass from NSObject and declare the property as visible from Objective-C and as dynamic:

class CounterModel : NSObject {

    @objc dynamic var value = 0
    @objc dynamic var messages = [String]()


Since iOS 10 there is a very comfortable block-based API to register for the change notifications:

model.observe(\.value, options: [.initial]) { (model, change) in
    self.label.text = String(model.value)

This also uses the Swift 4 keypath feature that allows to refer to properties in a strong type safe way. Hint: When dealing with compiler errors regarding type inference, it can help to write the full keypath including the type name to get better error messages:


This returns an NSKeyValueObservation object that you need to hold - when it is deallocated, you’ll receive no more notifications. If you want to observe multiple properties, you can store it in a list:

class CounterViewController: UIViewController {

    let model = CounterModel()
    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var messagesLabel: UILabel!
    var observers = [NSKeyValueObservation]()
    override func viewDidLoad() {
    func observeModel() {
        self.observers = [
    model.observe(\.value, options: [.initial]) { (model, change) in
        self.label.text = String(model.value)
    model.observe(\.messages, options: [.initial]) { (model, change) in
        self.messagesLabel.text = String(model.messages.joined(separator: "\n"))


More information