iOS开发之Notification与多线程

来源:互联网 发布:乐宝宝 乐普数据下载 编辑:程序博客网 时间:2024/06/06 05:49

一、概述

在多线程中,无论在哪个线程注册了观察者,Notification接收和处理都是在发送Notification的线程中的。所以,当我们需要在接收到Notification后作出更新UI操作的话,就需要考虑线程的问题了,如果在子线程中发送Notification,想要在接收到Notification后更新UI的话就要切换回到主线程。先看一个例子:

运行结果:

上面我们在主线程注册观察者,在子线程发送Notification,最后Notification的接收和处理也是在子线程。

 

二、重定向Notification到指定线程

当然,想要在子线程发送Notification、接收到Notification后在主线程中做后续操作,可以用一个很笨的方法,在 handleNotification 里面强制切换线程:

在简单情况下可以使用这种方法,但是当我们发送了多个Notification并且有多个观察者的时候,难道我们要在每个地方都手动切换线程?所以,这种方法并不是一个有效的方法。

 

最好的方法是在Notification所在的默认线程中捕获发送的通知,然后将其重定向到指定的线程中。关于Notification的重定向官方文档给出了一个方法:

Snip20170311_1

翻译成中文:

我们根据官方文档中的教程测试一下:

打印结果:

可以看到,运行结果结果我们想要的:在子线程中发送Notification,在主线程中接收与处理Notification。

上面的实现方法也不是绝对完美的,苹果官方指出了这种方法的限制:

(1)所有线程的Notification的处理都必须通过相同的方法(processNotification :)。

(2)每个对象必须提供自己的实现和通信端口。

更好但更复杂的方法是我们自己去子类化一个NSNotificationCenter,或者单独写一个类来处理这种转发。

 

除了上面苹果官方给我们提供的方法外,我们还可以利用基于block的NSNotification去实现,apple 从 ios4 之后提供了带有 block 的 NSNotification。使用方式如下:

其中:

  • 观察者就是当前对象
  • queue 定义了 block 执行的线程,nil 则表示 block 的执行线程和发通知在同一个线程
  • block 就是相应通知的处理函数

这个 API 已经能够让我们方便的控制通知的线程切换。但是,这里有个问题需要注意。就是其 remove 操作。

原来的 NSNotification 的 remove 方式如下:

但是带 block 方式的 remove 便不能像上面这样处理了。其方式如下:

其中 _observer 是 addObserverForName 方式的 api 返回观察者对象。这也就意味着,你需要为每一个观察者记录一个成员对象,然后在 remove 的时候依次删除。试想一下,你如果需要 10 个观察者,则需要记录 10 个成员对象,这个想想就是很麻烦,而且它还不能够方便的指定 observer 。因此,理想的做法就是自己再做一层封装,将这些细节封装起来。

0 0
原创粉丝点击