Key-value coding也即通过key来get和set对象的value,之所以这么做而不直接使用对象自带的getter和setter为了使用key-value observing功能。
那么什么是key-value observing呢?简而言之,key-value observing是一种消息通知的机制,和NSNotification的功能相似。使用NSNotification时,通过post来发消息,通过addObserver来观察消息。而key-value observing则更加动态地实现一个对象的改变,可以通知自己或另一个对象,进而采取相应的措施。
那么如何实现key-value observing呢?如之前所言,得先将对象的value和字符串的key绑定起来,这样做好像构造一个字典,通过key来访问value。NSKeyValueCoding协议中的方法实现了这种绑定。
- (void)setValue:(id)value forKey:(NSString *)key
由于NSObject实现了该方法,所以我们可以直接使用。绑定好key和value后,我们希望有某个对象B来监听对象A的变化。为了说明的方便,我以对象A为罪犯,对象B为警察来比喻。警察希望时时刻刻监听罪犯对象的行为变化。比如说警察通过罪犯的信用卡记录来判断罪犯是否犯罪,那么警察必须将自己和罪犯的信用卡记录进行绑定(注意警察只关注罪犯的部分属性,警察对罪犯每天吃什么并不关心,所以不需要绑定罪犯对象本身)。对于罪犯而言,警察是observer,监听属性是creditRecord。
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
具体到我们的例子就是下面的方法。
[criminal addObserver:policeman forKeyPath:@"creditRecord" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil ]
这里的keyPath就看得出之前为什么我们要做key-value的绑定工作了。那么为什么叫keyPath而不叫key呢?keyPath可以是一条完整的路径,假如警察想观察的不是罪犯的creditRecord,而是罪犯女友的creditRecord,那么对应的keyPath变为@"girlFriend.creditRecord"。留意下options, 它可以让警察选择观察记录下罪犯变化前后的值。
此时警察可以说已经”盯上“上了罪犯,接下来要处理的就是一旦罪犯的creditRecord出现变化,警察应该做出反应。我们可以在警察类中增加响应方法。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
具体到我们的例子是下面的方法。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"creditRecord"]) { NSInteger old = [change objectForKey:NSKeyValueChangeOldKey]; NSInteger new = [change objectForKey:NSKeyValueChangeNewKey]; NSLog("@The creditRecord has changed from %ld to %ld ", (long)old, (long)new ); } }
到此基本就结束了key-value observing的介绍~