常見的使用就不說了,說一說本身遇到的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];
});
複製代碼
爲什麼SDWebImage中對object使用weakSelfsession
FREQUENT CRASH in [SDWebImageDownloaderOperation cancelInternal] #1807多線程
使用queue和blockasync
使用mach port函數
上面說到,收發都在一個線程中,若是想要作到,在某個指定的線程接收通知,該如何作呢?蘋果文檔上說起了實現思路。
先簡單介紹下mach port,它主要用來線程間通訊。簡單來講,就是接收線程中註冊NSMachPort,在另外的線程中使用此port發送消息,則註冊線程會收到相應消息,調用handleMachMessage來處理。
主要思路:
定義一箇中間對象NotificationHandler,用來專門接收通知,包括一個隊列,接收通知的線程,mach port,lock。
首先NotificationHandler會註冊一個通知,對應的處理函數爲processNotification,當在其餘線程中post時,processNotification會被調用,進行以下處理。若是收到的通知跟指定的線程同樣,則處理消息,反之,則添加到隊列,同時經過port發送消息給指定線程。注意多線程中,對隊列的處理,要加鎖。
指定線程收到回調handleMachMessage,首先會將通知刪除,而後調用processNotification進行處理,繼續以上過程。