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