iOS 復(fù)習(xí)之OC-通知

image.png

通知

一、 通知實(shí)現(xiàn)原理是什么?

1、首先從結(jié)構(gòu)、如何存、通知名、事件幾個(gè)方面理解
結(jié)構(gòu):
NSNotification 通知的模型 name、object、userinfo.
NSNotificationCenter通知中心 負(fù)責(zé)發(fā)送NSNotification
NSNotificationQueue通知隊(duì)列 負(fù)責(zé)在某些時(shí)機(jī)觸發(fā) 調(diào)用NSNotificationCenter通知中心 post通知

  • 通知是結(jié)構(gòu)體通過雙向鏈表進(jìn)行數(shù)據(jù)存儲(chǔ)
// 根容器,NSNotificationCenter持有
typedef struct NCTbl {
  Observation       *wildcard;  /* 鏈表結(jié)構(gòu),保存既沒有name也沒有object的通知 */
  GSIMapTable       nameless;   /* 存儲(chǔ)沒有name但是有object的通知 */
  GSIMapTable       named;      /* 存儲(chǔ)帶有name的通知,不管有沒有object  */
    ...
} NCTable;

// Observation 存儲(chǔ)觀察者和響應(yīng)結(jié)構(gòu)體,基本的存儲(chǔ)單元
typedef struct  Obs {
  id        observer;   /* 觀察者,接收通知的對象  */
  SEL       selector;   /* 響應(yīng)方法     */
  struct Obs    *next;      /* Next item in linked list.    */
  ...
} Observation;
  • 主要是以key value的形式存儲(chǔ),這里需要重點(diǎn)強(qiáng)調(diào)一下 通知以 name和object兩個(gè)緯度來存儲(chǔ)相關(guān)通知內(nèi)容,也就是我們添加通知的時(shí)候傳入的兩個(gè)不同的方法.
通知的發(fā)送時(shí)同步的,還是異步的?
  • 同步發(fā)送.因?yàn)橐{(diào)用消息轉(zhuǎn)發(fā).所謂異步,指的是非實(shí)時(shí)發(fā)送而是在合適的時(shí)機(jī)發(fā)送,并沒有開啟異步線程.
NSNotificationCenter接受消息和發(fā)送消息是在一個(gè)線程里嗎?如何異步發(fā)送消息?
  • 是的, 異步線程發(fā)送通知?jiǎng)t響應(yīng)函數(shù)也是在異步線程。異步發(fā)送通知可以開啟異步線程發(fā)送即可.
NSNotificationQueue是異步還是同步發(fā)送?在哪個(gè)線程響應(yīng)?
  • NSNotificationCenter都是同步發(fā)送的,而這里介紹關(guān)于NSNotificationQueue的異步發(fā)送,從線程的角度看并不是真正的異步發(fā)送,或可稱為延時(shí)發(fā)送,它是利用了runloop的時(shí)機(jī)來觸發(fā)的.
  • 異步線程發(fā)送通知?jiǎng)t響應(yīng)函數(shù)也是在異步線程,主線程發(fā)送則在主線程.
NSNotificationQueue和runloop的關(guān)系

NSNotificationQueue依賴runloop. 因?yàn)橥ㄖ?duì)列要在runloop回調(diào)的某個(gè)時(shí)機(jī)調(diào)用通知中心發(fā)送通知.從下面的枚舉值就能看出來

// 表示通知的發(fā)送時(shí)機(jī)
typedef NS_ENUM(NSUInteger, NSPostingStyle) {
    NSPostWhenIdle = 1, // runloop空閑時(shí)發(fā)送通知
    NSPostASAP = 2, // 盡快發(fā)送,這種時(shí)機(jī)是穿插在每次事件完成期間來做的
    NSPostNow = 3 // 立刻發(fā)送或者合并通知完成之后發(fā)送
};
## 如何保證通知接收的線程在主線程

1、如果想在主線程響應(yīng)異步通知的話可以用如下兩種方式

1、在這個(gè)系統(tǒng)方法中指定隊(duì)列
- (id <NSObject>)addObserverForName:(nullable NSNotificationName)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block

2.NSMachPort的方式 通過在主線程的runloop中添加machPort,設(shè)置這個(gè)port的delegate,通過這個(gè)Port其他線程可以跟主線程通信,在這個(gè)port的代理回調(diào)中執(zhí)行的代碼肯定在主線程中運(yùn)行,所以,在這里調(diào)用NSNotificationCenter發(fā)送通知即可

頁面銷毀時(shí)不移除通知會(huì)崩潰嗎?
  • 會(huì)的
    iOS9.0之前,會(huì)crash,原因:通知中心對觀察者的引用是unsafe_unretained,導(dǎo)致當(dāng)觀察者釋放的時(shí)候,觀察者的指針值并不為nil,出現(xiàn)野指針.
    iOS9.0之后,不會(huì)crash,原因:通知中心對觀察者的引用是weak。
多次添加同一個(gè)通知會(huì)是什么結(jié)果?多次移除通知呢

多次添加同一個(gè)通知,會(huì)導(dǎo)致發(fā)送一次這個(gè)通知的時(shí)候,響應(yīng)多次通知回調(diào)。 多次移除通知不會(huì)產(chǎn)生crash。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 簡述 本文主要是針對iOS通知機(jī)制的全面解析,從接口到原理面面俱到。同時(shí)也解決了之前寫的文章阿里、字節(jié):一套高效的...
    iOS弗森科閱讀 1,427評論 0 7
  • 關(guān)鍵類 NSNotification 用于描述通知的類,一個(gè)NSNotification對象就包含了一條通知的信息...
    海菲菲菲閱讀 153評論 0 0
  • 通知機(jī)制想必大家都很熟悉,平常的開發(fā)中或多或少的應(yīng)該都用過。它是 Cocoa 中一個(gè)非常重要的機(jī)制,能把一個(gè)事件發(fā)...
    小小土豆dev閱讀 2,691評論 0 4
  • NSNotification是OC中一個(gè)調(diào)度消息通知的類, 采用單例模式設(shè)計(jì), 在程序中實(shí)現(xiàn)傳值,回調(diào)等應(yīng)用廣泛....
    mikey_Jiang閱讀 1,015評論 0 0
  • iOS 中通知機(jī)制詳解 NSNotification 通知的對象,一條通知就是一個(gè)NSNotification對象...
    你duck不必呀閱讀 3,048評論 1 3

友情鏈接更多精彩內(nèi)容