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/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,174评论 1 32
  • 1.设计模式是什么? 你知道哪些设计模式,并简要叙述? 设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类...
    司马DE晴空阅读 1,359评论 0 7
  • 1.设计模式是什么? 你知道哪些设计模式,并简要叙述?设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类型...
    龍飝阅读 2,245评论 0 12
  • 设计模式是什么? 你知道哪些设计模式,并简要叙述? 设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类型的...
    iOS菜鸟大大阅读 763评论 0 1
  • 好好整理你的家—— 伯特·海灵格 “ 好好整理你的家!” 这句话是什么意思?它表示你把东西通通井然有序地放好,于是...
    60723421d430阅读 406评论 0 0