标签: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