This protocol allows us to detect changes in property values of objects and works as follows:
To achieve this we only need to tell X that Y wants to be notified of such changes using the method addObserver:forKeyPath:options:context: defined in the protocol and perform the appropriate actions using the methodobserveValueForKeyPath:ofObject:change:context: on the object Y, since this is the message that is sent when the attribute changes its value.
How example we use this method to detect when a user selects or deselects an annotation (MKAnnotation) on a map (MKMapView). First I will show how to set up the project as a tutorial and below how to used exactly the KVO, if you already have your project, go directly to the second section.
Preparation
First create a new project using the Xcode template based on a view. We add to the project the MapKit Framework to use the map and annotations.
Then modify the view controller to add an IBOutlet as reference the map that will be added later. We will have to import the Framework.
We open the file MapKVOViewController.xib with Interface Builder and add a MKMapView to assign the previously created IBoutlet, also indicate that the delegate of the map will be the controller.
For annotations on the map we need to add another class to our project, in Xcode add a new class from a NSObject, we import here also the MapKit Framework. This class has to comply with the protocol so modify the MKAnnotation.h to do so.
How this class is only for a test, initialize variables at constant values, modify the .m to look like this.
To end the project preparation we only need to add an annotation on the map, for example use the viewDidLoad to do so. Remember you have to import your new class to use annotations on the map (here MapAnnotation).
Using KVO
In our example, object X is the view of the annotation, the pin you see on the map, in one hand we have the annotation itself and in another the view that represents it on the map, as the action of selection is made on the map, is the view of the annotation which has an attribute called selected, which is what we will want to monitor.
The object Y, will be our MapKVOViewController, which is responsible for adding annotations to the map.
First step, tell the object X we want to observe the selected attribute, if we want to do this with all the entries in the map, a good place is the method MapView:didAddAnnotationViews: in MKMapViewDelegate protocol, add this method to our controller and modify it to be like this
Please note that this will be done for each annotation, so if there are different types of annotations, you have to differentiate between which one you want to be notified and which ones not.
The method that interests us is addObserver:forKeyPath:options:context:, to the latter we will indicate who will be the observer, self, which attribute to observe, selected, with which options, NSKeyValueObservingOptionNew indicates that we want the new value, and a context that is used to give us more information, such as what we are seeing, here you can use nil if you observe only one thing, if you have to distinguished it is useful to use constants for each case, here we use
defined at the beginning of our .m
Finally, in order to take any action, once notified of the change, we need to overwrite the method observeValueForKeyPath:ofObject:change:context: