??在addObserver之前如果已經(jīng)有相同的通知在入宦,需要移除,否則post后乾闰,會(huì)調(diào)用多次。
??不管addObserver在哪個(gè)線(xiàn)程執(zhí)行涯肩,哪個(gè)線(xiàn)程執(zhí)行postNotificationName哪個(gè)線(xiàn)程執(zhí)行notificationAction,除非人為創(chuàng)建新的線(xiàn)程。但是如果創(chuàng)建新的線(xiàn)程竿报,則notificationAction不會(huì)執(zhí)行,eg:
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotificationName:object:) withObject:[NSNotification notificationWithName:@"name" object:nil] waitUntilDone:YES];
});
??postNotificationName發(fā)出通知以后阵幸,需要等待notificationAction執(zhí)行完畢才會(huì)返回(串行隊(duì)列順序執(zhí)行芽世,所以如果就是簡(jiǎn)單使用通知執(zhí)行復(fù)雜任務(wù)的話(huà),注意一下執(zhí)行順序吧\睢)旺矾。除非在方法中創(chuàng)建新的線(xiàn)程執(zhí)行整個(gè)方法,或者使用NSNotificationQueue嚎朽,但是NSNotificationQueue并不是創(chuàng)建子線(xiàn)程來(lái)執(zhí)行notificationAction。
??相反NSNotificationQueue與線(xiàn)程本身沒(méi)什么關(guān)系哟忍,每一個(gè)線(xiàn)程都只有一個(gè)NSNotificationQueue陷寝,且不能被其他線(xiàn)程使用。
NSNotificationQueue實(shí)際作用是:推遲通知發(fā)出粗蔚,聚合通知饶火。是根據(jù)runloop當(dāng)前不同的狀態(tài)和配置的NSPostingStyle來(lái)選擇執(zhí)行順序致扯。
另外当辐,在子線(xiàn)程中執(zhí)行enqueueNotification抖僵,notificationAction并不會(huì)被觸發(fā)(NSPostNow模式除外)耍群。換句話(huà)說(shuō)就是enqueueNotification只能在主線(xiàn)程中使用找筝。所以,如果執(zhí)行的是耗時(shí)操作曹抬,是會(huì)卡頓的急鳄。
之所以只能在主線(xiàn)程使用,是因?yàn)橛捎谟|發(fā)有延遲疾宏,為了保證可以正確觸發(fā),runloop就必須一直存在著为牍,只有主線(xiàn)程的runloop符合這個(gè)條件岩馍。而子線(xiàn)程在enqueueNotification后沒(méi)有等待回調(diào)執(zhí)行完畢就結(jié)束了。既然如此吟逝,只要讓子線(xiàn)程的runloop能一直存在赦肋,那么回調(diào)也可以在子線(xiàn)程中執(zhí)行。
NSPostingStyle有三種:
?NSPostNow:與postNotificationName相同
?NSPostASAP:不立即發(fā)出通知佃乘,而是在runloop匹配時(shí)調(diào)用,即:runloop處理事件源時(shí)
?NSPostWhenIdle:runloop閑置的時(shí)候post庞呕,即:runloop進(jìn)入睡眠時(shí)
[[NSNotificationQueue defaultQueue] enqueueNotification:[NSNotification notificationWithName:@"name" object:nil] postingStyle:2 coalesceMask:NSNotificationNoCoalescing forModes:@[NSDefaultRunLoopMode]];
??兩種添加通知的方法
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationAction:) name:@"name" object:nil];
id observe = [[NSNotificationCenter defaultCenter] addObserverForName:@"name" object:nil queue:[NSOperationQueue new] usingBlock:^(NSNotification * _Nonnull note) {
}];
第一種方法在iOS9.0后自動(dòng)釋放住练,不需要removeObserver。第二種方法需要?jiǎng)?chuàng)建id對(duì)象observe讲逛,最后釋放observe。
第一種方法NSNotificationCenter弱引用接收通知的對(duì)象蔚鸥,postNotificationName方法里面讓此對(duì)象執(zhí)行相應(yīng)的方法(invoke)许赃。因?yàn)槭侨跻茫砸坏┐藢?duì)象銷(xiāo)毀混聊,就不需要NSNotificationCenter再銷(xiāo)毀。
而第二種方法則是創(chuàng)建了一個(gè)強(qiáng)引用的對(duì)象(就跟第一種創(chuàng)建方法的self一樣)來(lái)保存通知的屬性,包括名稱(chēng)卧抗、線(xiàn)程、回調(diào)方法拙绊。在postNotificationName方法里面調(diào)用此對(duì)象,然后在對(duì)應(yīng)的線(xiàn)程中執(zhí)行回調(diào)方法标沪。在removeObserver方法里面將此對(duì)象釋放嗜傅。因?yàn)槭菑?qiáng)引用,所以需要調(diào)用removeObserver來(lái)通知NSNotificationCenter去銷(xiāo)毀吕嘀。
??通知合并:NSNotificationCoalescing,保證在runloop符合條件的情況下只執(zhí)行一次
參考:
http://www.reibang.com/p/86e1d721c6b1
https://www.mikeash.com/pyblog/friday-qa-2010-01-08-nsnotificationqueue.html