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 線程管理以及自動註銷開源方案

相關文章
相關標籤/搜索