Join Ron Buencamino for an in-depth discussion in this video What is key-value observation?, part of Communicating between Classes with Objective-C.
- The first pattern that we're going to go over is Key-Value Observation known to you now as KVO. KVO is an observer pattern and provides a way for objects to be notified of changes to specific properties of other objects by listening for changes on a particular key path. For example, a UIProgressView might observe the duration property of an AVPlayerItem so that it can update the time elapsed when playing an audio file.
Or we can observe the status property of a custom object that we create and, when we detect a change, we can make something happen. So, the main purpose of KVO is clear, allow any object to subscribe and be notified of changes in another object. And the best part of using KVO is that all of this is built right in to any object that is a subclass of NS object, so, you can freely use it in your programs.
So, to implement KVO, the first thing we need to do is register our observer. We do that by invoking the method, addObserver, forKeyPath, options, context, on the object that we'd like to observe. Those are a lot of arguments in that method so let's break it down to understand what we need. First is addObserver. This is the object that is registering for KVO notifications. This object must implement the observing method observeValueForKeyPath, ofObject, change, context.
The next value is key path and the key path is the property of the object that we want to observe. It accepts the NS string value. Next is options and this is referenced to the bitmask of NSKeyValueObservingOptions. The options that you get are NSKeyValueObservingOptionsNew, NSKeyValueObservingOptionsOld, NSKeyValueObservingOptionsInitial, and NSKeyValueObservingOptionsPrior.
The last argument is context and this is arbitrary information that is sent along to the observer. This parameter can be used to differentiate between observations of different objects that have the same key path. Now, whenever our object undergoes a change that we're observing, the observer receives a change notification. As an observer, we must implement the method observeValueForKeyPath, ofObject, to be notified of these changes.
Within this method, we usually have to do a check to see what key path is being passed to the method. If it matches, we can then take a look at the dictionary that's being passed to see the changes that occurred. As a rule of thumb, we're going to want to remove our observers whenever they aren't necessary. So we'll need to call the method removeObsever, forKeyPath, or removeObsever, forKeyPath, context, if you are passing additional context.
We do this because in the event of you not wanting to respond to any changes, like if you have a class being pushed off of the navigation stack, then removing the observer ensures that you do not have unwanted effects occurring in your program. There are exceptions to the rule, like if you want to have changes automatically occur for the user while they are viewing a modally displayed window or if you want a view to remain updated while you back navigate through your stack.
However, the lesson here is to be mindful of the observers your adding and to remove what you can when they aren't required anymore.