問題:
在GCD的dispatch_main_queue上runModel窗口會(huì)阻塞UI磨镶,定時(shí)器空免,動(dòng)畫等。
解決方案:
一般會(huì)使用這種方式來解決:
dispatch_async(dispatch_get_main_queue(), ^{
[self performSelectorOnMainThread:@selector(showAlert:) withObject:errorMsg waitUntilDone:NO];
或者
? ? ? ? ? ? ? [self performSelector:@selector(showAlert:) withObject:errorMsg afterDelay:0.1];
});
注意:
[self performSelector:@selector(showAlert:) withObject:errorMsg afterDelay:0.1];
使用這種方式時(shí),如果是在模態(tài)下墓卦,CGD回調(diào)中runModel彈出alter掷贾,必須先關(guān)掉之前的那個(gè)模態(tài)睛榄,再彈出新模態(tài)。否則第二次的模態(tài)不會(huì)彈出想帅,只會(huì)在第一個(gè)模態(tài)關(guān)掉后才彈出场靴。waitUntilDone:NO不會(huì)有這種情況。
原因:
runModalForWindow蘋果官網(wǎng)解釋是:打開一個(gè)模態(tài)事件循環(huán)港准,只處理該模態(tài)窗口下的事件旨剥,定時(shí)器等。在主線程中打開模態(tài)窗口只會(huì)影響非keyWindow的事件浅缸,但不影響主線程的UI操作轨帜。
GCD serial queues?是不可重入的,而runloop是可重入的衩椒。也就是說在主線程執(zhí)行一個(gè)block時(shí)蚌父,在該block執(zhí)行完成前哮兰,不會(huì)再次執(zhí)行另外一個(gè)派發(fā)到主線程的block。正常情況下runModal只會(huì)阻塞非keywindow的事件苟弛,但其他UI操作(更新Label值喝滞,動(dòng)畫效果不影響)。但如果在GCD dispatch_main_queue中runmModel窗口膏秫,就會(huì)阻塞整個(gè)主線程的UI事件(整個(gè)界面靜止了)右遭。這是因?yàn)橹骶€程的UI操作等待dispatch_main_queue的執(zhí)行完畢,而dispatch_main_queue又被runModel阻塞了缤削。
有人說了狸演,主線程阻塞了,為什么界面沒轉(zhuǎn)菊花僻他?runModel阻塞和線程阻塞不同宵距,前者阻塞非keyWindow上的關(guān)聯(lián)事件,后者阻塞整個(gè)線程的執(zhí)行吨拗,界面會(huì)轉(zhuǎn)菊花满哪。
通過解決方案也能說明,dispatch on the main queue isn’t the same as?performSelectorOnMainThread 劝篷。因?yàn)楹笳呤腔趓unloop的哨鸭。
link: