最近在github上看到了LRNotificationObserver这个项目,看了一下实现方式,作者通过ARC机制实例化注册对象子类与关联对象的方法来管理注册对象的生命周期。从而省去了系统通知移除的过程,本篇介绍该项目实现过程。

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_queueoperationQueue来判断是否切换队列,如果没有指定那么默认操作将在发送通知的线程中执行。

NSNotification系统通知优化的更多相关文章

  1. iOS-性能优化1

      iOS应用是非常注重用户体验的,不光是要求界面设计合理美观,也要求各种UI的反应灵敏,我相信大家对那种一拖就卡卡卡的 TableView 应用没什么好印象.还记得12306么,那个速度,相信大家都 ...

  2. iOS-性能优化2

    性能优化总结2 iOS应用是非常注重用户体验的,不光是要求界面设计合理美观,也要求各种UI的反应灵敏,我相信大家对那种一拖就卡卡卡的 TableView 应用没什么好印象.还记得12306么,那个速度 ...

  3. 深入浅出-iOS程序性能优化 (转载)

    iOS应用是非常注重用户体验的,不光是要求界面设计合理美观,也要求各种UI的反应灵敏,我相信大家对那种一拖就卡卡卡的 TableView 应用没什么好印象. iOS应用是非常注重用户体验的,不光是要求 ...

  4. 1024程序员节宅男节日快乐 -- JAVA快速开发平台,JEECG 3.8宅男优化版本发布

    JEECG 3.8 版本发布,系统全面升级,重构上传组件.优化代码生成器机制! 导读   ⊙平台性能优化,系统更稳定,速度闪电般提升 ⊙系统上传组件全面重构,使用plupload组件,解决flash的 ...

  5. iOS--App功耗优化

    良好的用户体验需要如下要素: 电池寿命长.随着能效降低,电池寿命也会降低.但用户想让自己的移动设备全天候待命. 速度快.iOS系统处理复杂操作时仍能提供很好的性能. 响应快.同一时刻消耗太多资源会使U ...

  6. iOS性能优化技巧

    通过静态 Analyze 工具,以及运行时 Profile 工具分析性能瓶颈,并进行性能优化.结合本人在开发中遇到的问题,可以从以下几个方面进行性能优化. 一.view优化 1.不透明的View 设置 ...

  7. 推荐:Java性能优化系列集锦

    Java性能问题一直困扰着广大程序员,由于平台复杂性,要定位问题,找出其根源确实很难.随着10多年Java平台的改进以及新出现的多核多处理器,Java软件的性能和扩展性已经今非昔比了.现代JVM持续演 ...

  8. 优化神器 beamoff

    http://files.cnblogs.com/files/yipu/beamoff.zip csdn上有下载:http://download.csdn.net/download/bytige/83 ...

  9. VMWare 装mac os x 一个必备优化神器 beamoff

    https://blog.csdn.net/whitehack/article/details/47074403/ VMWare 装mac os x 一个必备优化神器 beamoff 2015年07月 ...

随机推荐

  1. BZOJ 3551 Peaks加强版

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3551 题意:给出一个图,n个点,m条边.边有权值点也有权值.若干询问,(v,x,k),问从 ...

  2. 【转载】前端面试“http全过程”将所有HTTP相关知识抛出来了...

    原文:前端面试“http全过程”将所有HTTP相关知识抛出来了... 来一篇串通,一个http全过程的问题,把所有HTTP相关知识点都带过一遍 http全过程 输入域名(url)-->DNS映射 ...

  3. 【转载】nedmalloc结构分析

    原文:nedmalloc结构分析 nedmalloc是一个跨平台的高性能多线程内存分配库,很多库都使用它,例如:OGRE.现在我们来看看nedmalloc的实现 (以WIN32部分为例)    位操作 ...

  4. Linux简介与厂商版本

    Linux简介与厂商版本   作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 1. Linux简介 Linux可以有狭义和广义两种 ...

  5. kafka单节点部署无法访问问题解决

    场景:在笔记本安装了一台虚拟机, 在本地的虚拟机上部署了一个kafka服务: 写了一个测试程序,在笔记本上运行测试程序,访问虚拟机上的kafka,报如下异常: 2015-01-15 09:33:26 ...

  6. spring的自动装配(default-autowire="byName")

    自动装配,官方给出的定义是这样:Spring IoC容器可以自动装配(autowire)相互协作bean之间的关联关系.因此,如果可能的话,可以自 动让Spring通过检查BeanFactory中的内 ...

  7. linux安装phpstorm出现 Startup Error: Unable to detect graphics environment

    在centos6.2下在安装phpstorm下遇到 Startup Error: Unable to detect graphics environment 其中jdk安装的版本是 1.7.0_79  ...

  8. 笔记本_thinkpad_e40

    1. 0578A69 2.驱动下载 相关地址 XPhttp://think.lenovo.com.cn/support/driver/detail.aspx?docID=DR1253259153348 ...

  9. [转载] 深入理解 docker ulimit

    深入理解docker ulimit 2015年7月23日 10:00 阅读 12778 [编者的话]Docker大规模应用后,如果你没踩过坑,说出去肯定没人信.昨天就遇到一个ulimit的经典问题:业 ...

  10. commons-logging日志系统

    日志的重要性是随着系统的膨胀而显现的,在一个庞大的系统中查错没有各种日志信息    是寸步难行的.所以在系统加入日志是必须的. 最原始的日志方式,就是在程序的适当地方添加System.out.prin ...