在主调度队列上显示UI元素会导致元素出现然后消失

时间:2012-08-09 18:09:45

标签: objective-c cocoa-touch grand-central-dispatch

我想在开始长任务之前显示进度HUD,并在任务完成后将其关闭。现在UI冻结了一段时间,然后HUD显示一秒钟然后消失。再过4-5秒后,任务结束并显示结果,但进度HUD已经消失。

- (void) addProcess:(NSString *)searchTerm
{
    dispatch_sync(dispatch_get_main_queue(), ^{
        UIApplication *app = [UIApplication sharedApplication];
        app.networkActivityIndicatorVisible = YES;
        [SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeGradient];
    });

    //DO SOME VERY LONG STUFF HERE

    dispatch_sync(dispatch_get_main_queue(), ^{
        UIApplication *app = [UIApplication sharedApplication];
        app.networkActivityIndicatorVisible = NO;
        [SVProgressHUD dismiss];
    });
}

我使用SVProgressHUD进行HUD进度。我使用addProcess

调用方法dispatch_async()

如果我使用旧版+[NSThread detach...],它可以完美运行,但我不想再使用它了。

1 个答案:

答案 0 :(得分:8)

有几件事:

  1. 关键观察是始终使用dispatch_async,除非您需要dispatch_sync。您不需要在此处进行同步操作,因此只需使用dispatch_async进行UI更新。

  2. 如果您从主队列运行addProcess,则无需将第一个UI更新分发回主队列。显然,如果你是从后台队列中运行它,那么你就可以了。

  3. 最初的问题是在addProcess内调度到后台队列,这对我来说更有意义(保持所有GCD内容很好地封装)。你已经更新了你的答案,说你是通过dispatch_async([self addProcess])来调用它的(我假设你的意思是全局队列,而不是主队列),我不那么疯狂了。我在下面的代码示例中解决了这两种情况。

  4. 所以,简而言之,如果你通过[self addProcess]调用它(没有将它本身发送到后台队列),我建议:

    - (void) addProcess:(NSString *)searchTerm
    {
        UIApplication *app = [UIApplication sharedApplication];
        app.networkActivityIndicatorVisible = YES;
        [SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeGradient];
    
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
            //DO SOME VERY LONG STUFF HERE
    
            dispatch_async(dispatch_get_main_queue(), ^{
                UIApplication *app = [UIApplication sharedApplication];
                app.networkActivityIndicatorVisible = NO;
                [SVProgressHUD dismiss];
            });
        });
    }
    

    或者,或者,

    - (void) addProcess:(NSString *)searchTerm
    {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
            dispatch_async(dispatch_get_main_queue(), ^{
                UIApplication *app = [UIApplication sharedApplication];
                app.networkActivityIndicatorVisible = YES;
                [SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeGradient];
            });
    
            //DO SOME VERY LONG STUFF HERE
    
            dispatch_async(dispatch_get_main_queue(), ^{
                UIApplication *app = [UIApplication sharedApplication];
                app.networkActivityIndicatorVisible = NO;
                [SVProgressHUD dismiss];
            });
        });
    }
    

    如果你正在......

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self addProcess]; 
    });
    

    那就是:

    - (void) addProcess:(NSString *)searchTerm
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            UIApplication *app = [UIApplication sharedApplication];
            app.networkActivityIndicatorVisible = YES;
            [SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeGradient];
        });
    
        //DO SOME VERY LONG STUFF HERE
    
        dispatch_async(dispatch_get_main_queue(), ^{
            UIApplication *app = [UIApplication sharedApplication];
            app.networkActivityIndicatorVisible = NO;
            [SVProgressHUD dismiss];
        });
    }