dispatch_sync阻止我的UI,我无法点击任何按钮

时间:2013-05-25 20:02:56

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

我有两个带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];
    });
});

3 个答案:

答案 0 :(得分:1)

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

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

将阻止您的用户界面,直到[self getFotos]返回。

答案 1 :(得分:0)

一些反应。

  1. 你在这里使用的模式并没有多大意义。从您的代码示例中做出一些推论,我认为所需的模式将是:

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

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

    • 执行完成块的最后dispatch_barrier_async(即表示已完成调度到并发队列的所有其他块),这将执行dispatch_async(不是{{1通常)返回主队列以停止HUD。

  2. 此代码示例中没有任何内容可以提示任何会导致您的UI无响应的内容,因此为了清晰/简洁,我必须怀疑您删除的代码部分中的某些内容。通常,有两件事可能会使您的用户界面无法响应:

    • 显然,如果有任何调度回主队列的速度很慢。例如,你有一个sync方法,但是我们不知道它是做什么的,但是如果它很慢,那就会导致问题。在这个类别的片段中没有任何明显的东西,但这是一类需要注意的问题。

    • 如果有一些东西意外地进入了与UI相关的背景队列,那么问题就更微妙了。具有讽刺意味的是,这通常会导致UI冻结一点。您必须分享您在该区块中执行的操作的详细信息,以便我们进一步为您提供建议。

    但这些只是我跳出来的两件事,可能会导致您的用户界面暂时无法响应。


  3. 完全与您的表现问题无关,但我通常不建议使用旧式动画。作为the docs say,“...在iOS 4.0及更高版本中不鼓励这种方法。”所以我建议删除说:

    的行
    getFotos

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

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

答案 2 :(得分:0)

您可能希望在此处使用调度组。将一个块放到背景中&在禁用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(),
                   ^{ /* ... */ });
               });