iOS中Notification是同步還是異步的問題剖析

一、通知在主線程中默認(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)行選擇;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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