The key value of the encoding allows you to retrieve or modify the property of an object using a string at run time instead of having to write code that compiles with a fixed property from the start:
NSNumber* foo = [myPopup valueForKey: @"selectedItemIndex"]; [myPopup setValue: @15 forKey: @"selectedItemIndex"];
A good example for this is NSTableView on a Mac, where you can simply set an identifier in each column of the table that matches your property of the model object that it should display, and then your data source simply calls -valueForKey: / - setValue: forKey: with identifier column as a key and values ββare largely displayed / set by themselves. You simply add the correct columns to the table view in XIB.
After that, monitoring of key values ββhas been added and allows you to register to receive notifications of changes made to another object. You register your interest by doing:
void* gMyKVOContext = &gMyKVOContext;
Whenever this property changes, -observeValueForKeyPath: ofObject: change: context: will be called on the object that you specified as an observer. Thus, you implement this as:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if( context == gMyKVOContext && [keyPath isEqualToString: @"interestingProperty"] ) {
The advantage here is that you receive a call in real time when another property changes. Note that objects should do a little work, so these notifications are sent, so not all properties are observable by keywords. Also note that some objects may be in an unacceptable state if two related properties change immediately after another: you receive a notification after the first property has been changed, which now contradicts the second, and only then the second property is changed, for which it is notified. Therefore, during the first observer callback, the object may be in a strange state, so be careful how you react to it.
To make a property observable, either use the standard @synthesized implementation when you define it, or define it yourself, configure, for example:
-(void) setFoo: (int)inFoo { [self willChangeValueForKey: @"foo"]; _foo = inFoo; [self didChangeValueForKey: @"foo"]; }
Then always go through the setter to change it, don't change _foo directly. If you have related properties that may conflict with each other, as mentioned above, a good way to avoid this is to always change them as in pairs (then you cannot use KVC). To do this, perform a combined setter, for example:
-(void) setFoo: (int)inFoo bar: (int)inBar { [self willChangeValueForKey: @"foo"]; [self willChangeValueForKey: @"bar"]; _foo = inFoo; _bar = inBar; [self didChangeValueForKey: @"bar"]; [self didChangeValueForKey: @"foo"]; }
In this way, both notifications are sent while the properties are in the correct states.