简析KVOController实现原理
KVOController是FaceBook的一个开源库,提供了方便的姿势让你去使用KVO。
https://github.com/facebook/KVOController
大概的用法如下:
[self.KVOControllerobserve:target keyPath:keyPath options:NSKeyValueObservingOptionNew block:^(id observer,id object,NSDictionary *change) {
id newValue = change[NSKeyValueChangeNewKey];
}];
observe操作完成后,在控制器 dealloc 时隐观测者会被隐式的移除,非常方便。
我们来看看KVOController的实现流程:
KVOController实现流程:
1.Observer会创建一个FBKVOController的属性;
2.FBKVOController中包含一个NSMapTable的成员属性,用来存储observer的KVO信息;
3.FBKVOController创建一个_FBKVOInfo类型的实例,实例中存储了和KVO操作相关的信息(keypath等),然后将需要观察的对象Target作为Key,_FBKVOInfo的实例加入数组(对同一个Target的不同keypath的多次KVO操作)并把数组作为Value,存入步骤2中的mapTable中;
4.FBKVOController会调用_FBKVOSharedController的单例中的方法,同时将步骤3创建的info和观察的target传入给这个方法,这个单例进行了最终的KVO操作;
5._FBKVOSharedController的单例调用系统KVO方法,将自己作为观察者来观察Target对象。
在Observer内存被释放,执行dealloc时,其创建的FBKVOController属性的dealloc会通过KVOInfoMap找到所有KVO的对象,并执行移除观察的操作,十分巧妙的设计!
但是在使用的过程中还是有一些注意事项的:
首先,FBKVOController使用block来传递系统KVO的回调,因此要注意retain cycle。
其次,在使用的过程中,target不能强引用observer,否则也会形成retain cycle。我在上面的实现流程图中增加了一些标注来说明这个retain cycle是如何形成的:
retain cycle形成轨迹
红色的箭头代表了内存持有的方向,可以很清楚的看到形成了cycle。
针对v1.1版本,具有了一下新的特性:
针对 iOS/OS X/tvOS/watchOS 的 Carthage 支持 ( by @lexrus by @nlutsenko);
提供了对 tvOS/watchOS 官方的 CocoaPods 支持 ( by @acerbetti, by @nlutsenko);
所有的 API 都具有了 nullability annotations ( by @nlutsenko);
所有的对象集合(object collections)现在都具有泛型 ( by @nlutsenko);
新的工具宏(macros)以提供对键直观查路径(Key-Value Observing Paths)有效性的编译时检查 (by @nlutsenko);
支持 Xcode 7.3 和 Apple 开发最新的工具链 ( by @nlutsenko);
提升:
NSObject+FBKVOController分类(category)现在被放置在一个独立的文件中(#36 by @ashton-w);
当尝试监控一个已经被监控的对象时不再有多余的警告信息;
修复:
修复了当尝试从监控执行块(observing block)中移除监控者时可能引发的崩溃行为 ( by @siyusong);
修复并且提升了文档的可读性 (by @TongKuo by @jeffreyjackson by @ashton-w by @jcavar by @coeur )
Key-value 的监控是一个 MVC 应用中非常有用的技术,但接口丑陋古老。KVOController (来自 Facebook)构建了一个基于 Cocoa 的 time-tested key-value 监控实现,提供简单方便、线程安全的 API。
好处包括:
使用 Blocks、自定义 Actions 或者 NSKeyValueObserving 回调进行通知.
观测者移除时无异常
控制器 dealloc 时隐式的观测者移除
提升使用 NSKeyValueObservingInitial 的性能
线程安全并提供在观测者恢复时额外的保护 Thread-safety with special guards against observer resurrection – rdar://15985376.