标签:style io ar color os 使用 sp for strong
FBKVOController主要包括3个类,_FBKVOInfo,FBKVOController,_FBKVOSharedController。对外暴露的是FBKVOController。
1、FBKVOInfo:是个结构类,model。包含一些变量。
@implementation _FBKVOInfo { @public __weak FBKVOController *_controller; NSString *_keyPath; NSKeyValueObservingOptions _options; SEL _action; void *_context; FBKVONotificationBlock _block; }
action,block都是处理函数,当监听到value变化时调用的。在_FBKVOSharedController中会被调用
2、_FBKVOSharedController:主要用来添加监听,并且监听到事件之后的处理。
@implementation _FBKVOSharedController { NSHashTable *_infos; OSSpinLock _lock; }
_infos存储被监听的对象。
_lock是自旋锁,在多线程同时访问公共对象时保证线程安全。这里是在对_infos进行操作的时候使用。它快速,安全,性能消耗小。
3、FBKVOController:对外提供接口的类。它包含的变量也比较简单
@implementation FBKVOController { NSMapTable *_objectInfosMap; OSSpinLock _lock; }
NSMapTable *_objectInfosMap;(存储键值对,object对应其要监听的keypath)
OSSpinLock _lock;(同上,自旋锁)
NSMapTable:NSDictionary的进化,可以设置对象的强弱引用。
NSHashTable:NSSet的进化,同样也可以设置对象的强弱引用。
FBKVOController的使用
1、initWithObserver生成FBKVOController对象。
2、- (void)observe:(id)object keyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options block:(FBKVONotificationBlock)block;
使用block或者SEL都可以。
以上2步就是调用的主流程。
具体实现:
主要讲调用第二步之后内部是怎么实现的。
1、首先initWithObserver生成了FBKVOInfo,初始化一些信息。然后调用_observe函数,将info当做参数传入。使用锁,保证线程安全。
- (void)_observe:(id)object info:(_FBKVOInfo *)info { // lock OSSpinLockLock(&_lock); NSMutableSet *infos = [_objectInfosMap objectForKey:object]; // check for info existence _FBKVOInfo *existingInfo = [infos member:info]; if (nil != existingInfo) { NSLog(@"observation info already exists %@", existingInfo); // unlock and return OSSpinLockUnlock(&_lock); return; } // lazilly create set of infos if (nil == infos) { infos = [NSMutableSet set]; [_objectInfosMap setObject:infos forKey:object]; } // add info and oberve [infos addObject:info]; // unlock prior to callout OSSpinLockUnlock(&_lock); [[_FBKVOSharedController sharedController] observe:object info:info]; }
mapTable以obj作为key,NSMutableSet(对象类型为FBKVOInfo)作为value。
首先检查存不存在info。存在则直接返回,不存在就添加到set中,然后调用FBKVOSharedController的observe函数。
该函数主要就是addobserver。
- (void)observe:(id)object info:(_FBKVOInfo *)info { if (nil == info) { return; } // register info OSSpinLockLock(&_lock); [_infos addObject:info]; OSSpinLockUnlock(&_lock); // add observer [object addObserver:self forKeyPath:info->_keyPath options:info->_options context:(void *)info]; }
当有监听事件发生时,监听函数会被调用。
此时的处理,就是调用对应controller传入的回调函数,block或者是action。这样就完成了事件的监听处理。
#pragma clang使用来去掉编译器警告。没有实现selector的警告。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { NSAssert(context, @"missing context keyPath:%@ object:%@ change:%@", keyPath, object, change); _FBKVOInfo *info; { // lookup context in registered infos, taking out a strong reference only if it exists OSSpinLockLock(&_lock); info = [_infos member:(__bridge id)context]; OSSpinLockUnlock(&_lock); } if (nil != info) { // take strong reference to controller FBKVOController *controller = info->_controller; if (nil != controller) { // take strong reference to observer id observer = controller.observer; if (nil != observer) { // dispatch custom block or action, fall back to default action if (info->_block) { info->_block(observer, object, change); } else if (info->_action) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [observer performSelector:info->_action withObject:change withObject:object]; #pragma clang diagnostic pop } else { [observer observeValueForKeyPath:keyPath ofObject:object change:change context:info->_context]; } } } } }
还有对应的unobserve,将object从mapTable中移除掉。
- (void)_unobserve:(id)object info:(_FBKVOInfo *)info { // lock OSSpinLockLock(&_lock); // get observation infos NSMutableSet *infos = [_objectInfosMap objectForKey:object]; // lookup registered info instance _FBKVOInfo *registeredInfo = [infos member:info]; if (nil != registeredInfo) { [infos removeObject:registeredInfo]; // remove no longer used infos if (0 == infos.count) { [_objectInfosMap removeObjectForKey:object]; } } // unlock OSSpinLockUnlock(&_lock); // unobserve [[_FBKVOSharedController sharedController] unobserve:object info:registeredInfo]; }
同样调用FBKVOSharedController的unobserve。最后还是调用NSObject对象的removeObserver
- (void)unobserve:(id)object info:(_FBKVOInfo *)info { if (nil == info) { return; } // unregister info OSSpinLockLock(&_lock); [_infos removeObject:info]; OSSpinLockUnlock(&_lock); // remove observer [object removeObserver:self forKeyPath:info->_keyPath context:(void *)info]; }
标签:style io ar color os 使用 sp for strong
原文地址:http://my.oschina.net/u/861778/blog/354285