January 30, 2018 · Ralf Ebert » iOS Developer Blog »

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:

\CounterModel.value

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() {
        super.viewDidLoad()
        
        observeModel()
    }
    
    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

Btn read 3c0e607615 iOS Developer Blog
Btn subscribe 930758687e Subscribe: Email · Twitter
Btn training bbbdf557d2 Next iOS training: 25. Februar - 01. März 2019, Stuttgart
Btn about 5378472193 About me · Contact