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
類似焰扳,但是兩者又有區(qū)別倦零。
NSDictionary提供了key-to-object的映射。NSDictionary
的object的位置是由key的hash值來索引的吨悍。由于對象存儲在特定位置扫茅,因此要求key的值不能改變。因此育瓜,NSDictionary
始終復(fù)制key到它的私有位置葫隙。這個key的復(fù)制行為也是NSDictionary
如何工作的基礎(chǔ),但這也有一個限制:你可以只使用Objective-C對象作為NSDictionary
的key躏仇,如果它支持NSCopying
協(xié)議恋脚。此外,key應(yīng)該是小且高效的焰手,以至于復(fù)制的時候不會對CPU和內(nèi)存造成負擔糟描。而NSMapTable
是一種一般意義上的映射。不僅支持key-to-object,同時支持object-to-object映射书妻。
pthread_mutex_t
是一個互斥鎖船响,用來保證多線程安全。
然后看初始化函數(shù),對傳入的observer進行weak持有见间,根據(jù)retainObserved來設(shè)置NSPointerFunctionOptions的值聊闯,初始化互斥鎖。
FBKVOController.png
再來看一下第一個API函數(shù)米诉。如果object, keyPath或者block為空馅袁,則直接返回。接著根據(jù)傳入的參數(shù)初始化_FBKVOInfo
這個內(nèi)部數(shù)據(jù)結(jié)構(gòu),然后調(diào)用[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
這個類注冊瘾杭,然后轉(zhuǎn)發(fā)注冊觀察,并且更新info的state哪亿。
observe:info:.png
最后看一下observeValueForKeyPath:ofObject:change:context
這個方法粥烁。首先根據(jù)context上下文獲取info信息。接著判斷info的controller和observer是否存在(之前是weak持有)蝇棉。根據(jù)info的block或者action活著override進行轉(zhuǎn)發(fā)讨阻。
observeValueForKeyPath:ofObject:change:context.png