Swift之正确使用通知

2017-11-14  本文已影响0人  小小土豆dev

本文主要介绍,如何在项目中正确的使用通知,在使用之前,先了解几个概念:

概念一:NotificationCenter(通知中心)

通知中心实际上是iOS程序内部之间的一种消息广播机制,主要为了解决应用程序内部不同对象之间解耦而设计。它是基于观察者模式设计的,不能跨应用程序进程通信,当通知中心接收到消息之后会根据内部的消息转发表,将消息发送给订阅者。

通知是同步的,接收通知的对象会在发送通知对象的线程中执行方法,当所有接收对象执行完消息后,发送通知对象才会执行接下来的代码。

每一个iOS程序都有一个唯一的通知中心,它是系统创建好的一个单例类,不需要我们自己去创建。

1.获取通知中心

class var default: NotificationCenter{ get }

2.在通知中心注册一个通知

func addObserver(_ observer: Any, selector aSelector: Selector, name aName: NSNotification.Name?, object anObject: Any?)

概念二:Notification(通知)

Notification就是我们发送的消息对象,有以下三个常用的属性:

1.通知的名称,用来标示一个通知,一般为字符串

public var name:Notification.Name

2.任意想要携带的对象,通常为发送者自己

public var object:Any? 

3.附加信息

public var userInfo: [AnyHashable: Any]?

概念三:移除通知

在通知中心注册通知后,当注册对象销毁时如果不在通知中心中移除通知,当收到通知时,会造成向野指针对象发送消息,会crash。

1.移除所有通知

func removeObserver(_observer:Any)

2.根据通知名称,移除通知

func removeObserver(_observer:Any, name aName:NSNotification.Name?, object anObject:Any?)


下面介绍项目中如何正确的使用通知

方式一:异步发送通知

上面说过,通知是同步的,它会等到所有接受者执行完代码后,才会执行接下来的代码,如果在当前线程直接发送通知,就会阻塞当前线程,所以将发送通知放在全局并发队列中:

1.发送通知

DispatchQueue.global().async{

    NotificationCenter.default.post(name:NSNotification.Name(rawValue: "name"),

                                                    object:nil,

                                                 userInfo:nil)

}

2.注册通知

NotificationCenter.default.addObserver(self,

                        selector:#selector(login(_:)),

                          name:NSNotification.Name(rawValue:"name"),

                         object:nil

)

3.收到通知时,执行的方法

func login(_notification:Notification) {

    DispatchQueue.main.async{

      // 如果更新UI,需要在主线程中

    }

}

4.移除通知

NotificationCenter.default.removeObserver(self, name:NSNotification.Name(rawValue:"name"), object:nil)


方式二:使用通知队列发送通知

NotificationQueue(通知队列)

通知中心收到发送者发出的通知后,会立刻分发给监听者,但是如果把通知放在通知队列中,通知就可以等到某些特定时刻再发出,比如等到之前发出的通知在runloop中处理完,或者runloop空闲的时候。它就像通知中心的缓冲池,把一些不着急发出的通知存在通知队列中。

存储在通知队列中的通知会以先进先出的方式发出。

每个线程有一个默认的通知队列,它和通知中心关联着,是一个单例类。你也可以自己为线程或者通知中心创建多个通知队列。

1.获取通知队列

class var `default`: NotificationQueue { get }

2.通知队列发送通知

func enqueue(_ notification: Notification, postingStyle: NotificationQueue.PostingStyle, coalesceMask: NotificationQueue.NotificationCoalescing, forModes modes: [RunLoopMode]?)

参数介绍:

notification:要发送的通知消息对象

postingStyle:发送方式,有三种:whenIdle(空闲时发送)、asap(尽快发送)、now(立即发送)

coalesceMask:过滤通知方式,有三种:none(不合并)、onName(按通知的名字合并)、onSender(按通知的发送者合并)

forModes:指定了某种特定runloop mode,一般为nil

下面用通知队列发送一个消息,接收通知的代码就不写了,和方式一里面的一样:

// 初始化消息通知对象

let notification = Notification.init(name:Notification.Name(rawValue: "name"),

                                                  object:nil,

                                                userInfo: userInfo)

// 获取通知队列

let nq = NotificationQueue.default

// 发送通知

nq.enqueue(notification,

postingStyle:NotificationQueue.PostingStyle.asap,// 发送方式,立即发送

coalesceMask:NotificationQueue.NotificationCoalescing.onName,// 根据通知名称过滤

forModes:nil)

具体使用哪种方式,要根据项目业务逻辑判断。如果通知发送时间间隔短,比较频繁,优先级不高,简易使用通知队列,因为有过滤功能,可以选择性过滤,减少频繁发送通知带来的额外开销。

上一篇下一篇

猜你喜欢

热点阅读