FBKVOConroller是Facebook开源的替代KVO的解决方案。它用block解决了以前使用KVO时代码散乱的缺点。
FBKVOController的核心代码一共4个类:
NSObject+FBKVOController.h
NSObject+FBKVOController.m
FBKVOController.h
FBKVOController.m
NSObject+FBKVOController.m是一个Category。通过AssociateObject给NSObject提供一个Retain和nonRetain的KVOController。
FBKVOController.m一共可以分为3部分:
_FBKVOInfo
_FBKVOSharedController
FBKVOController
先来看一下FBKVOController这个类。首先该对象有2个属性,NSMapTable和pthread_mutex_t。
其中NSMapTable和NSDictionary类似,但是两者又有区别。
NSDictionary提供了key-to-object的映射。NSDictionary的object的位置是由key的hash值来索引的。由于对象存储在特定位置,因此要求key的值不能改变。因此,NSDictionary始终复制key到它的私有位置。这个key的复制行为也是NSDictionary如何工作的基础,但这也有一个限制:你可以只使用Objective-C对象作为NSDictionary的key,如果它支持NSCopying协议。此外,key应该是小且高效的,以至于复制的时候不会对CPU和内存造成负担。而NSMapTable是一种一般意义上的映射。不仅支持key-to-object,同时支持object-to-object映射。
pthread_mutex_t是一个互斥锁,用来保证多线程安全。
然后看初始化函数,对传入的observer进行weak持有,根据retainObserved来设置NSPointerFunctionOptions的值,初始化互斥锁。

FBKVOController.png
再来看一下第一个API函数。如果object, keyPath或者block为空,则直接返回。接着根据传入的参数初始化_FBKVOInfo这个内部数据结构,然后调用[self _observe:object info:info]。

observe.png
接着看一下- (void)_observe:(id)object info:(_FBKVOInfo *)info这个方法。先开一个锁来检查被观察的object的NSMutableSet是否存在,如果存在,则返回,解锁。如果不存在,为这个object添加一个NSMutableSet,接着NSMutableSet添加所传入的info,解锁。最后就是[[_FBKVOSharedController sharedController] observe:object info:info]。

- (void)_observe:info:.png
那接着来看下_FBKVOSharedController这个类。_FBKVOSharedController这个类类似于一个中间件的注册表。所有的观察信息都由_FBKVOSharedController这个类注册,然后转发注册观察,并且更新info的state。

observe:info:.png
最后看一下observeValueForKeyPath:ofObject:change:context这个方法。首先根据context上下文获取info信息。接着判断info的controller和observer是否存在(之前是weak持有)。根据info的block或者action活着override进行转发。

observeValueForKeyPath:ofObject:change:context.png
作者:alvin_wang
链接:http://www.jianshu.com/p/1bf111d7d2de
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
网友评论