Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects.
The KVO mechanism is widely used in Foundation and AppKit (less so in UIKit). I frequently use it when working with NSOperations
to observe isFinished
. My biggest gripe with KVO is that all KVO changes are sent to one method, observeValueForKeyPath:ofObject:change:context:
. The implementation of this method often becomes a ugly mass of if-else statements.
In an attempt to do away with observeValueForKeyPath:ofObject:change:context:
I have written an NSObject
category which augments KVO. It has three methods:
@interface NSObject (EMKKVOSelector)
-(void)EMK_addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath selector:(SEL)observationSelector;
-(void)EMK_addObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context selector:(SEL)observationSelector;
-(void)EMK_removeObserver:(NSObject *)anObserver withKeyPath:(NSString *)keyPath selector:(SEL)observationSelector;
@end
The selectors used for observationSelector must match one of the following method signatures:
-(void)noArguments
-(void)oneArgument:(NSString *)keyPath
-(void)twoArguments:(NSString *) object:(id)
-(void)threeArguments:(NSString *) object:(id) change:(NSDictionary)
-(void)fourArguments:(NSString *) object:(id) change:(NSDictionary) context:(void *)
eg:
-(void)refreshView;
-(void)refreshCellValue:(NSString *)keyPath representingPersonObject:(id)person;
All invocations to EMK_addObserver...
methods must be balanced with a call to EMK_removeObserver...
. These methods are not compatible with the standard KVO methods.
The code has only been briefly tested. Internally the code uses associate references and properties so it’s strictly Objective-C 2.0. Other people have implemented similar KVO fixes all of which offer slightly different features: