写在前面
每次使用KVO和通知我就觉得是一件麻烦的事情,即便谈不上麻烦,也可说是不方便吧,对于KVO,你需要注册,然后实现监听方法,最后还要移除,通知当然也需要移除操作,这使得相关逻辑的代码过于分散,控制器搞得乱乱的,而且总有时候会忘记移除什么的,总之感觉不太好,所以我想如果能有方法添加一个KVO或者通知后能够省略后面移除或者实现监听方法步骤的话会多好,所以我就尝试写了一个分类,这个分类的目的在于尽可能简化KVO和通知的步骤,对于KVO,你只需要一句代码就可完成监听,无需自己手动移除,通知也差不多,接口如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/** * 通过Block方式注册一个KVO,通过该方式注册的KVO无需手动移除,其会在被监听对象销毁的时候自动移除 * * @param keyPath 监听路径 * @param block KVO回调block,obj为监听对象,oldVal为旧值,newVal为新值 */ - (void)xw_addObserverBlockForKeyPath:(NSString*)keyPath block:(void (^)(id obj, id oldVal, id newVal))block; /** * 通过block方式注册通知,通过该方式注册的通知无需手动移除,同样会自动移除 * * @param name 通知名 * @param block 通知的回调Block,notification为回调的通知对象 */ - (void)xw_addNotificationForName:(NSString *)name block:(void (^)(NSNotification *notification))block; |
使用也很简单咯,github地址如下:XWEasyKVONotification,你只需要导入NSObject+XWAdd
这个分类,然后调用上面两个接口即可完成KVO和通知,事例代码如下
1 2 3 4 5 6 7 |
//监听_objA的name属性 [_objA xw_addObserverBlockForKeyPath:@"name" block:^(id obj, id oldVal, id newVal) { NSLog(@"kvo,修改name为%@", newVal); }]; [self xw_addNotificationForName:@"XWTestNotificaton" block:^(NSNotification *notification) { NSLog(@"收到通知:%@", notification.userInfo); }]; |
是不是非常简单,再也不用关心忘记移除导致的崩溃了,而且代码也集中,看着也更舒服了
原理
1、由于KVO和通知都差不多,原理部分通过KVO的接口的的实现原理进行说明,考虑到代码的统一我首先考虑到使用block,同时为了block能回调,我们需要一个内部的对象target的来实现KVO的代码,在监听到值改变的时候通过这个对象来回调block,同时一个target应该对应一个keyPath,并且可应该对应多个Block,因为我们可能对一个keyPath进行多处监听,这个类的具体代码大致如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
@interface _XWBlockTarget : NSObject /**添加一个KVOblock*/ - (void)xw_addBlock:(void(^)(__weak id obj, id oldValue, id newValue))block; @end @implementation _XWBlockTarget{ //保存所有的KVOblock NSMutableSet *_blockSet; } - (instancetype)init { self = [super init]; if (self) { _blockSet = [NSMutableSet new]; } return self; } - (void)xw_addBlock:(void(^)(__weak id obj, id oldValue, id newValue))block{ [_blockSet addObject:[block copy]]; } //KVO的真正实现 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ if (!_blockSet.count) return; BOOL prior = [[change objectForKey:NSKeyValueChangeNotificationIsPriorKey] boolValue]; //只接受值改变时的消息 if (prior) return; NSKeyValueChange changeKind = [[change objectForKeyline" id="crayon-58128f56bf956324848126-32"> NSKeyValueChange changeKind = [[change objectForKey想如果能有方法添加一个KVO或者通知后能够省略后面移除或者实现监听方法步骤的话会多好,所以我就尝试写了一个分类,这个分类的目的在于尽可能简化KVO和通知的步骤,对于KVO,你只需要一句代码就可完成监听,无需自己手动移除,通知也差不多,接口如下:
使用也很简单咯,github地址如下:XWEasyKVONotification,你只需要导入
是不是非常简单,再也不用关心忘记移除导致的崩溃了,而且代码也集中,看着也更舒服了 原理1、由于KVO和通知都差不多,原理部分通过KVO的接口的的实现原理进行说明,考虑到代码的统一我首先考虑到使用block,同时为了block能回调,我们需要一个内部的对象target的来实现KVO的代码,在监听到值改变的时候通过这个对象来回调block,同时一个target应该对应一个keyPath,并且可应该对应多个Block,因为我们可能对一个keyPath进行多处监听,这个类的具体代码大致如下:
|