NSNotification系统通知优化
2016-07-11 17:55
204 查看
最近在github上看到了LRNotificationObserver这个项目,看了一下实现方式,作者通过ARC机制实例化注册对象子类与关联对象的方法来管理注册对象的生命周期。从而省去了系统通知移除的过程,本篇介绍该项目实现过程。
移除
这是正常使用通知的情形,这样使用存在两个问题
每次使用都需要手动移除观察者。
如果在主线程注册观察者然后在线程B中发送通知,如果通知事件是更新UI那么就会出现问题因为此时是在线程B操作而不是主线程。
实例化注册对象
这种方法需要声明一个
这种情况下作者把销毁的方法写在了
使用类方法不用实例化对象
虽然不用实例化
通过运行时关联对象的方法将
当收到通知后线程会自动切换到
作者通过是否指定
NSNotificationCenter 通知存在的问题
注册[[NSNotificationCenter defaultCenter] addObserver:anObserver selector:@selector(handleNotification:) name:aNotificationName object:anObjectThatFiresTheNotification];
移除
[[NSNotificationCenter defaultCenter] removeObserver:anObserver name:aNotificationName object:anObjectThatFiresTheNotification];
这是正常使用通知的情形,这样使用存在两个问题
每次使用都需要手动移除观察者。
如果在主线程注册观察者然后在线程B中发送通知,如果通知事件是更新UI那么就会出现问题因为此时是在线程B操作而不是主线程。
LRNotificationObserver
LRNotificationObserver对象的内部持有
NSNotificationCenter对象实际上是对
NSNotificationCenter基础功能进一步的封装。
LRNotificationObserver自动管理观察者
LRNotificationObserver有两种方法初始化
实例化注册对象
@property (nonatomic, strong) LRNotificationObserver *backgroundObserver; self.backgroundObserver = [LRNotificationObserver observerForName:UIApplicationDidEnterBackgroundNotification block:^(NSNotification *note) { // Do appropriate background task }];
这种方法需要声明一个
LRNotificationObserver对象作为属性,根据ARC内存管理当对象销毁时对象的属性也会一起销毁
这种情况下作者把销毁的方法写在了
LRNotificationObserver对象的
dealloc方法中。
- (void)dealloc { [self stopObserving]; } - (void)stopObserving { [_notificationCenter removeObserver:self name:_name object:_object]; [self clear]; } - (void)clear { _block = nil; _targetAction = nil; _operationQueue = nil; _dispatchQueue = nil; }
使用类方法不用实例化对象
[LRNotificationObserver observeName:UIApplicationDidReceiveMemoryWarningNotification owner:self block:^(NSNotification *note) { // Purge unnecessary cache }];
虽然不用实例化
LRNotificationObserver但是要传入
owner参数,
owner相当于一个钩子,让其与
LRNotificationObserver对象进行关联。
+ (void)addObserver:(LRNotificationObserver *)observer asPropertyOfOwner:(id)owner { objc_setAssociatedObject(owner, (__bridge void *)observer, observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC); }
通过运行时关联对象的方法将
LRNotificationObserver对象与
owner对象关联,当
owner销毁时关联断开,
LRNotificationObserver对象不被任何对象持有销毁。执行
dealloc方法
线程安全
LRNotificationObserver可以指定通知方法执行队列
[LRNotificationObserver observeName:@"someNotificationThatShouldUpdateTheUI" object:anObject owner:anOwner dispatch_queue:dispatch_get_main_queue() target:viewController selector:@selector(methodToBeExecutedOnMainThread:)];
当收到通知后线程会自动切换到
dispatch_queue置顶队列所在的线程中。
- (void)executeNotificationFiredBlock:(dispatch_block_t)block { if (self.operationQueue) { if ([NSThread isMainThread] && self.operationQueue == [NSOperationQueue mainQueue]) { block(); } else { [self.operationQueue addOperationWithBlock:block]; } } else if (self.dispatchQueue) { if ([NSThread isMainThread] && self.dispatchQueue == dispatch_get_main_queue()) { block(); } else { dispatch_async(self.dispatchQueue, block); } } else { block(); } }
作者通过是否指定
dispatch_queue与
operationQueue来判断是否切换队列,如果没有指定那么默认操作将在发送通知的线程中执行。
相关文章推荐
- NSNotification系统通知优化
- Hadoop概念学习系列之hadoop细节知识题小整理(二十四)
- [Effective JavaScript 笔记]第60条:支持方法链
- Strider安装(Ubuntu)
- 系统上线流程规范
- 机器学习关键问题阐述
- Nginx源码分析 - 主流程篇 - 全局变量cycle初始化
- SpringMVC详细运行流程图
- RCNN学习笔记(6):You Only Look Once(YOLO):Unified, Real-Time Object Detection
- php保存execl
- Android判断用户的网络类型(2/3/4G、wifi)
- LeetCode 242. Valid Anagram
- java设计模式学习资料汇总
- 页面 html5鼠标滚动全屏图片倾斜分割切换特效
- c++ 全局变量、局部变量、静态全局变量、静态局部变量的区别
- 获取系统的当前单独日期时间
- How to solve SQL Server Error 1222 i.e Unlock a SQL Server table
- session入mysql (入库)
- RCNN学习笔记(5):faster rcnn
- Activity的四种启动模式-图文并茂