一、通知在主線程中默認(rèn)是同步的
NSNotification默認(rèn)在主線程中通知是同步的,當(dāng)通知產(chǎn)生時,通知中心會一直等待所有的觀察者都收到并且處理通知結(jié)束,才會返回到發(fā)送通知的地方繼續(xù)執(zhí)行后邊的代碼(所以處理通知的方法中如果存在耗時操作將會引起程序卡頓);
代碼示例如下:
- (void)textNotifation {
#define XYNotificationTestName @"XYNotificationTestName"
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(progress) name:XYNotificationTestName object:nil];
NSLog(@"即將發(fā)出通知");
[[NSNotificationCenter defaultCenter] postNotificationName:XYNotificationTestName object:nil];
NSLog(@"處理發(fā)出通知的下一條代碼");
}
- (void)progress {
sleep(10);
NSLog(@"通知處理結(jié)束");
}
打印出來結(jié)果為:
2019-04-20 13:58:52.004154+0800 TechnolgyTest[45755:5701088] 即將發(fā)出通知
2019-04-20 13:59:02.004102+0800 TechnolgyTest[45755:5701088] 通知處理結(jié)束
2019-04-20 13:59:02.004269+0800 TechnolgyTest[45755:5701088] 處理發(fā)出通知的下一條代碼
以上示例證明通知在主線程中默認(rèn)是同步的,這就要求我們在開發(fā)中要避免在通知的處理方法中添加耗時操作。
二、讓通知異步的方法
1、將通知的發(fā)送放到子線程中
代碼示例如下
NSLog(@"即將發(fā)出通知");
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:XYNotificationTestName object:nil];
});
NSLog(@"處理發(fā)出通知的下一條代碼");
這個時候控制臺得到的結(jié)果為:
2019-04-20 14:23:56.403482+0800 TechnolgyTest[46411:5715874] 即將發(fā)出通知
2019-04-20 14:23:56.403639+0800 TechnolgyTest[46411:5715874] 處理發(fā)出通知的下一條代碼
2019-04-20 14:24:06.404744+0800 TechnolgyTest[46411:5715945] 通知處理結(jié)束
由此我們可以得出結(jié)論: 將通知的發(fā)送方法防到子線程中可以使通知變成異步的。
2、將通知的處理方法放到子線程中
我們在主線程中post通知,同時將處理方法的代碼放到子線程中,代碼示例:
- (void)progress {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
sleep(2);
NSLog(@"通知處理結(jié)束");
});
}
這個時候控制臺得到的結(jié)果為:
2019-04-20 14:27:36.520127+0800 TechnolgyTest[46539:5718264] 即將發(fā)出通知
2019-04-20 14:27:36.520284+0800 TechnolgyTest[46539:5718264] 處理發(fā)出通知的下一條代碼
2019-04-20 14:27:46.521147+0800 TechnolgyTest[46539:5718320] 通知處理結(jié)束
3、通知的發(fā)送可以添加到NSNotificationQueue異步通知緩沖隊(duì)列中
我們將通知放到通知隊(duì)列中發(fā)送,代碼示例如下:
NSLog(@"即將發(fā)出通知");
NSNotification *notification = [NSNotification notificationWithName:XYNotificationTestName object:nil];
[[NSNotificationQueue defaultQueue] enqueueNotification:notification postingStyle:NSPostASAP];
NSLog(@"處理發(fā)出通知的下一條代碼");
此時得到的結(jié)果為:
2019-04-20 14:30:40.302657+0800 TechnolgyTest[46639:5720748] 即將發(fā)出通知
2019-04-20 14:30:40.302846+0800 TechnolgyTest[46639:5720748] 處理發(fā)出通知的下一條代碼
2019-04-20 14:30:42.313722+0800 TechnolgyTest[46639:5720748] 通知處理結(jié)束
由此我們得出結(jié)論: 可以將通知放入NSNotificationQueue中并指定為NSPostASAp或者NSPostWhenIdle類型發(fā)送,可以使的通知的處理變?yōu)楫惒?;?em>注意指定NSPostNow模式立即發(fā)送通知,得到的結(jié)果仍然是同步執(zhí)行)
注:NSNoticicationQueue
NSNoticicationQueue是一個通知緩沖隊(duì)列,通常以FIFO(先進(jìn)先出)的規(guī)則維護(hù)通知隊(duì)列的發(fā)送。
向通知隊(duì)列中添加通知有三種枚舉類型:
NSPostASAp (盡快發(fā)送)
NSPostWhenIdle (空閑時發(fā)送)
NSPostNow (立刻發(fā)送)
我們可以根據(jù)通知的緊急程度進(jìn)行選擇;