KVO进阶(一)
前言
KVO(key value observing),可以监听指定键,值的改变。与KVC相似,KVO也是以非正式协议的方式出现Foundation/NSKeyValueObserving.h。
正文
相信大家对KVO的基本用法早已烂熟于心,这里不再介绍
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
在监听对象具体属性时,多数情况下会这样写
[obj addObserver:self forKeyPath:@"xxx" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
基于苹果的MVC设计原理,KVO最常出现的应用场景就是解耦View和Model。以上代码中obj即Model,self即Controller,当Model内容出现变动告知Controller,由Controller再更新UI。
先来看一幅从NSHipster上截取的表
form nshipster
KVO中context:后的参数是(void *)context,很明显这里应该写NULL而不是nil
接着context继续说,这个参数好像并没有什么卵用,不然干嘛每次都传空?
试想这样一种情况,B -> A -> NSObject,C -> NSObject,C中有属性obj
0-0
0-1
此时a、b同时观察c的obj属性,如果在某种情况下c的obj发生改变只想告知a而不告知b或者相反,这个时候怎么做?很简单,在B中重写-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context,如果不重写怎么完成需求?这个时候context就可以作为唯一标示符出场了。
同时还可以看到,obj的值改变后是先告知b再告知a的,也就是说谁最后观察谁最先被告知,类似于先进后出(这里与继承关系无关)。利用这一特性,又可以搞些小动作,比如跨类设置KVO的依赖(后续文章会介绍同一类的不同属性如何设置KVO依赖)。
KVO与通知一样,可以是任意对象观察任意对象即“多对多”,observer并不仅限于Controller。