1、NSNotification消息的同步性

①NSNotification使用的是同步操作。即如果你在程序中的A位置post了一个NSNotification,在B位置注册了一个observer,通知发出后,必须等到B位置的通知回调执行完以后才能返回到A处继续往下执行。

因此,不要过多的或者低效的使用NSNotification,《Cocoa基本原理指南》一文推荐的方式是通过一些“中间的”观察者将通告的结果传递给它们可以访问的对象。

②如果想让NSNotification的post处和observer处异步执行,可以通过NSNotificationQueue实现。

2、多个观察者的执行顺序

对于同一个通知,如果注册了多个观察者,则这多个观察者的执行顺序和他们的注册顺序是保持一致的。

3、NSNotification通知转发线程

①NSNotificationCenter在转发NSNotification消息的时候,在哪个线程中post,就在哪个线程中转发。换句话说,不管你的observer是在哪个线程,observer的回调方法执行线程都和post的线程保持一致。

②如果想让post的线程和转发的线程不同,可以通过NSNotification重定向技术实现。

4、addObserver和removeObserver必须成对出现

官方文档中是这样描述的:

The notification center does not retain its observers, therefore, you must ensure that you unregister observers (usingremoveObserver: or removeObserver:name:object:) before they are deallocated. (If you don’t, you will generate a runtime error if the center sends a message to a freed object.)

再addObserver的时候,notification center并不增加观察者对象的引用计数,因此,在观察者对象被释放之前我们必须保证它们被从观察队列中移除,否则后果很明显!

5、Notification与多线程

前几天与同事讨论到Notification在多线程下的转发问题,所以就此整理一下。

先来看看官方的文档,是这样写的:

In a multithreaded application, notifications are always delivered in the thread in which the notification was posted, which may not be the same thread in which an observer registered itself.

翻译过来是:

在多线程应用中,Notification在哪个线程中post,就在哪个线程中被转发,而不一定是在注册观察者的那个线程中。

也就是说,Notification的发送与接收处理都是在同一个线程中。为了说明这一点,我们先来看一个示例:

代码清单1:Notification的发送与处理

@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];NSLog(@"current thread = %@", [NSThread currentThread]);[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:TEST_NOTIFICATION object:nil];dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{[[NSNotificationCenter defaultCenter] postNotificationName:TEST_NOTIFICATION object:nil userInfo:nil];});
}- (void)handleNotification:(NSNotification *)notification
{NSLog(@"current thread = %@", [NSThread currentThread]);NSLog(@"test notification");
}@end

其输出结果如下:

可以看到,虽然我们在主线程中注册了通知的观察者,但在全局队列中post的Notification,并不是在主线程处理的。所以,这时候就需要注意,如果我们想在回调中处理与UI相关的操作,需要确保是在主线程中执行回调。

这时,就有一个问题了,如果我们的Notification是在二级线程中post的,如何能在主线程中对这个Notification进行处理呢?或者换个提法,如果我们希望一个Notification的post线程与转发线程不是同一个线程,应该怎么办呢?我们看看官方文档是怎么说的:

For example, if an object running in a background thread is listening for notifications from the user interface, such as a window closing, you would like to receive the notifications in the background thread instead of the main thread. In these cases, you must capture the notifications as they are delivered on the default thread and redirect them to the appropriate thread.

这里讲到了“重定向”,就是我们在Notification所在的默认线程中捕获这些分发的通知,然后将其重定向到指定的线程中。

一种重定向的实现思路是自定义一个通知队列(注意,不是NSNotificationQueue对象,而是一个数组),让这个队列去维护那些我们需要重定向的Notification。我们仍然是像平常一样去注册一个通知的观察者,当Notification来了时,先看看post这个Notification的线程是不是我们所期望的线程,如果不是,则将这个Notification存储到我们的队列中,并发送一个信号(signal)到期望的线程中,来告诉这个线程需要处理一个Notification。指定的线程在收到信号后,将Notification从队列中移除,并进行处理。

这种实现方式的具体解析及其局限性大家可以参考官方文档Delivering Notifications To Particular Threads,在此不多做解释。当然,更好的方法可能是我们自己去子类化一个NSNotificationCenter,或者单独写一个类来处理这种转发。

 

参考

  1. Notification Programming Topics

  2. Threading Programming Guide

  3. NSNotificationCenter is thread-safe NOT

  4. Observers and Thread Safety

转载于:https://www.cnblogs.com/malikun/p/5640652.html

NSNtification 在多线程中的运用相关推荐

  1. 【Linux】多线程中使用fork()

    (最核心的东西我在下面用红色字体标出来了,理解了那块,这些东西都是就理解了!) 在本篇文章开始之前,需要大家先了解线程和进程,这位大哥讲的言简意赅:进程和线程的主要区别(总结)_kuangsongha ...

  2. java闭合数据_java多线程中线程封闭详解

    线程封闭的概念 访问共享变量时,通常要使用同步,所以避免使用同步的方法就是减少共享数据的使用,这种技术就是线程封闭. 实现线程封闭的方法 1:ad-hoc线程封闭 这是完全靠实现者控制的线程封闭,他的 ...

  3. java多线程中的join方法详解

    java多线程中的join方法详解 方法Join是干啥用的? 简单回答,同步,如何同步? 怎么实现的? 下面将逐个回答. 自从接触Java多线程,一直对Join理解不了.JDK是这样说的:join p ...

  4. 了解多线程中的yield

    2019独角兽企业重金招聘Python工程师标准>>> 最近在学习多线程这一块,发现里面有好多让人产生误区的地方,今天我来分析下java多线程中的yield功能,希望其他朋友也可以从 ...

  5. 解决DataGridView在多线程中无法显示滚动条的问题

    解决DataGridView在多线程中无法显示滚动条的问题 参考文章: (1)解决DataGridView在多线程中无法显示滚动条的问题 (2)https://www.cnblogs.com/roph ...

  6. VMware 虚拟化编程(8) — 多线程中的 VixDiskLib

    目录 目录 前文列表 多线程注意事项 多线程中的 VixDiskLib 前文列表 VMware 虚拟化编程(1) - VMDK/VDDK/VixDiskLib/VADP 概念简析 VMware 虚拟化 ...

  7. 如何在多线程中调用winform窗体控件2——实例篇

    如何在多线程中调用winform窗体控件2--实例篇 针对之前文章<如何在多线程中调用winform窗体控件>,下面举个我项目中的实际案例,这是一个我自定义控件在异步设置焦点时的代码.在新 ...

  8. android串口补位,Rust多线程中的消息传递机制

    代码说话. use std::thread; use std::sync::mpsc; use std::time::Duration; fn main() { let (tx, rx) = mpsc ...

  9. JAVA多线程中join()方法的详细分析

    虽然关于讨论线程join()方法的博客已经非常极其特别多了,但是前几天我有一个困惑却没有能够得到详细解释,就是当系统中正在运行多个线程时,join()到底是暂停了哪些线程,大部分博客给的例子看起来都像 ...

最新文章

  1. vuecli3 引入全局scss变量_vuecli3 从搭建到优化
  2. Native层HIDL服务的注册原理-Android10.0 HwBinder通信原理(六)
  3. html与css结合动效案例,CSS3制作动画效果例子
  4. boost::mp11::mp_for_each相关用法的测试程序
  5. 不断尝试,终能到达彼岸
  6. pip install scrpy 报错: command 'gcc' failed with exit status 1
  7. Delphi6及SqlServer对于生僻字䶮的支持测试
  8. HTMO DOM部分---小练习;列表之间移动、日期选择、好友选中、滑动效果、滚动条效果、飞入飞出效果。...
  9. 正面管教之PHP_主题体验活动之亲密关系
  10. Eclipse—在Eclipse中如何创建JavaWeb工程
  11. 苹果手机自带表格软件_苹果手机还自带扫描仪,没想到今天才发现
  12. 计算机英语文体特点,公共英语五级写作文体特点分析
  13. 【李宏毅】机器学习-RNN
  14. POI 写word,添加标题,表格,图片,自动生成目录,合并单元格
  15. JXL开发Excel文档中文教程
  16. 一本大学计算机专业最新排名,中国校友会网2018中国大学计算机类各本科专业排行榜...
  17. LK光流金字塔算法原理及C++实现
  18. 【项目实战】 改造原前端ViewUI框架,使其支持ElementUI 与 Avue
  19. 使用Linux Deploy搭建个人云盘,跟百度说拜拜
  20. Riak - 背景篇(2)

热门文章

  1. hive 配置用户名_Hive的安装及配置
  2. python3一爬虫库url_python3爬虫之Urllib库(一)
  3. 测控技术与仪器专业c语言教学视频,测控技术与仪器要学哪些基础和专业课程...
  4. Qt_数据库基本操作(未完成)
  5. VS2015配置Opencv
  6. 苹果计算机怎么添加在快捷方式,如何在 iPhone 主屏幕上添加文件快捷方式?
  7. python装饰器模式带参数_python 装饰器模式 我的理解
  8. 结构体指针memcpy出错_关于memset和memcpy的使用,尤其对结构体进行初始化和拷贝的问题 | 学步园...
  9. htnl 点击系统记录显示在右侧_软网推荐:时间管理者 记录工时与薪酬
  10. printf函数输出格式汇总