iOS中NSNotification的套路

常见的使用就不说了,说一说本身遇到的tipgit

添加和移除

  • 屡次添加会屡次收到消息,因此确保添加和移除是一一对应的。

同步发送通知

这一点与KVO相似,即发送通知的时候,全部接收者都收到通知才算作发送完成。github

发送通知与响应通知都在一个线程

这一点与KVO相似。 NSNotification不能跨线程:即响应通知的action,默认是与postNotification在同一个线程的,若想在指定线程中执行响应通知的方法,可使用带有block的addObserver方法,或者使用dispatch_async(xxx)。segmentfault

若是须要跨线程,可使用带有block的通知接口。安全

如AFN中:bash

dispatch_group_async(manager.completionGroup ?: url_session_manager_completion_group(), manager.completionQueue ?: dispatch_get_main_queue(), ^{
            if (self.completionHandler) {
                self.completionHandler(task.response, responseObject, error);
            }

            dispatch_async(dispatch_get_main_queue(), ^{
                [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingTaskDidCompleteNotification object:task userInfo:userInfo];
            });
        });
复制代码

为了保证在主线程发送通知。 这一点能够在一些网络请求数据到达时, 用于刷新界面。网络

dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:kNotificationFilterMaterialRequestFinished object:self userInfo:nil];
    });
复制代码

线程安全及一个死锁案例

object,observer的weak仍是unsafe

为什么SDWebImage中对object使用weakSelfsession

SDWebImage的改动

FREQUENT CRASH in [SDWebImageDownloaderOperation cancelInternal] #1807多线程

在指定线程接收通知

  1. 使用queue和blockasync

  2. 使用mach port函数

上面说到,收发都在一个线程中,若是想要作到,在某个指定的线程接收通知,该如何作呢?苹果文档上说起了实现思路。

先简单介绍下mach port,它主要用来线程间通讯。简单来讲,就是接收线程中注册NSMachPort,在另外的线程中使用此port发送消息,则注册线程会收到相应消息,调用handleMachMessage来处理。

主要思路:

定义一个中间对象NotificationHandler,用来专门接收通知,包括一个队列,接收通知的线程,mach port,lock。

首先NotificationHandler会注册一个通知,对应的处理函数为processNotification,当在其余线程中post时,processNotification会被调用,进行以下处理。若是收到的通知跟指定的线程同样,则处理消息,反之,则添加到队列,同时经过port发送消息给指定线程。注意多线程中,对队列的处理,要加锁。

指定线程收到回调handleMachMessage,首先会将通知删除,而后调用processNotification进行处理,继续以上过程。

参考

你可能不知道的 Notification

NSNotification 线程管理以及自动注销开源方案

相关文章
相关标签/搜索