【问题标题】:dispatch_sync block my UI, I cant click any buttondispatch_sync 阻塞了我的用户界面,我无法点击任何按钮
【发布时间】:2013-05-25 20:02:55
【问题描述】:

我有 2 个带有 dispatch_sync 的块,当第一个块结束时,我向用户显示窗口并开始运行第二个块。但是在第二个区块结束之前,我不会点击屏幕上的任何按钮..

看代码:

[HUD showUIBlockingIndicatorWithText:@"Loading..."];
dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^ {
        dispatch_sync(dispatch_get_main_queue(), ^{
                [UIView beginAnimations:@"fade" context:nil];
                [UIView setAnimationDuration:0.5];
                self.capa.alpha = 0.0;
                [UIView commitAnimations];
                [HUD hideUIBlockingIndicator];
        });
});

dispatch_barrier_async(queue, ^ {
    //code executed in the background
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"entrou na foto");
        //[self getFotos];
    });
});

【问题讨论】:

    标签: ios objective-c objective-c-blocks dispatch dispatch-async


    【解决方案1】:

    如果你在主线程调用任何代码,它会阻塞你的 UI,所以调用

    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"entrou na foto");
        [self getFotos];
    });
    

    [self getFotos] 返回之前将阻止您的用户界面。

    【讨论】:

    • 就是这样,马塞尔,非常感谢。我这样做了:dispatch_queue_t backgroundQueue = dispatch_queue_create("com.mycompany.myqueue", 0); dispatch_barrier_async(queue, ^ { dispatch_async(backgroundQueue, ^{ [self getFotos] ; }); });而且效果很好!!!非常感谢你!
    【解决方案2】:

    几个反应。

    1. 您在这里使用的模式不太合理。从您的代码示例中做出一些推论,我原以为所需的模式是:

      • 只需在主队列中启动 HUD(或一些旋转活动指示器视图)即可;

      • 在后台队列中调度所有单独的耗时进程;如果它们可以同时运行,您将使用dispatch_async 到您的queue;和

      • 对你的完成块做一个最后的dispatch_barrier_async(即你指示所有其他分派到你的并发队列的块都完成了),然后dispatch_async(通常不是sync)返回到主队列停止HUD。

    2. 此代码示例中没有任何内容会暗示任何会使您的 UI 无响应的内容,因此我不得不怀疑您为了清晰/简洁而删除的代码部分中的某些内容。一般来说,有两件事可能会导致您的 UI 无响应:

      • 很明显,如果有任何东西被分派回主队列,那是很慢的。例如,你有一个getFotos 方法,但我们不知道它是做什么的,但如果它很慢,就会导致问题。在您的 sn-p 的这一类中显然没有什么,但这是需要注意的一类问题。

      • 更微妙的问题可能是,如果其中有一些与 UI 相关的内容意外滑入该后台队列。具有讽刺意味的是,这通常会导致 UI 冻结一段时间。您必须在发送到后台的那个区块中分享您正在执行的操作的详细信息,以便我们为您提供进一步的建议。

      但我觉得只有这两件事会导致你的 UI 暂时无响应。


    与您的性能问题完全无关,但我通常不建议使用旧式动画。正如the docs say,“......在iOS 4.0 及更高版本中不鼓励使用此方法。”所以我建议删除以下内容:

    [UIView beginAnimations:@"fade" context:nil];
    [UIView setAnimationDuration:0.5];
    self.capa.alpha = 0.0;
    [UIView commitAnimations];
    

    相反,我建议您使用基于块的动画,例如:

    [UIView animateWithDuration:0.5 animations:^{
        self.capa.alpha = 0.0;
    }];
    

    【讨论】:

    • 谢谢罗伯。正如@Marcel 所说,错误是因为我在主线程上运行,它阻塞了我的 UI。感谢动画的提示,我在这里更改了更优雅的代码。
    【解决方案3】:

    您可能希望在此处使用调度组。在禁用 UI 的情况下将块发送到后台并发送到组中,然后您可以生成一个等待线程调用 dispatch_group_wait 阻塞它,直到任务完成以重新启用 UI。只有禁用的部分被锁定。其他一切都会正常工作

    dispatch_group_t group = dispatch_group_create();
    dispatch_group_async(group, /* queue */, ^{ /* ... */ });
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
                   ^{
                       dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
                       // This thread will be blocked until background tasks are done.
                       dispatch_async(dispatch_get_main_queue(),
                       ^{ /* ... */ });
                   });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多