GCD与runModalForWindow

问题:

在GCD的dispatch_main_queue上runModel窗口会阻塞UI,定时器,动画等。

解决方案:

一般会使用这种方式来解决:

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];

使用这种方式时,如果是在模态下,CGD回调中runModel弹出alter,必须先关掉之前的那个模态,再弹出新模态。否则第二次的模态不会弹出,只会在第一个模态关掉后才弹出。waitUntilDone:NO不会有这种情况。

原因:

runModalForWindow苹果官网解释是:打开一个模态事件循环,只处理该模态窗口下的事件,定时器等。在主线程中打开模态窗口只会影响非keyWindow的事件,但不影响主线程的UI操作。

GCD serial queues 是不可重入的,而runloop是可重入的。也就是说在主线程执行一个block时,在该block执行完成前,不会再次执行另外一个派发到主线程的block。正常情况下runModal只会阻塞非keywindow的事件,但其他UI操作(更新Label值,动画效果不影响)。但如果在GCD dispatch_main_queue中runmModel窗口,就会阻塞整个主线程的UI事件(整个界面静止了)。这是因为主线程的UI操作等待dispatch_main_queue的执行完毕,而dispatch_main_queue又被runModel阻塞了。

有人说了,主线程阻塞了,为什么界面没转菊花?runModel阻塞和线程阻塞不同,前者阻塞非keyWindow上的关联事件,后者阻塞整个线程的执行,界面会转菊花。

通过解决方案也能说明,dispatch on the main queue isn’t the same as performSelectorOnMainThread 。因为后者是基于runloop的。

link:

https://www.thecave.com/2015/08/10/dispatch-async-to-main-queue-doesnt-work-with-modal-window-on-mac-os-x/

你可能感兴趣的:(GCD与runModalForWindow)