3

我想在开始一项长任务之前显示一个进度 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...],它可以完美地工作,但我不想再使用它了。

4

1 回答 1

8

A couple of things:

  1. The key observation is to always use dispatch_async unless you need dispatch_sync. You don't need synchronous operation here, so just use dispatch_async for your UI updates.

  2. If you're running addProcess from the main queue, it doesn't need to dispatch the first UI update back to the main queue. Obviously, if you're running this from a background queue, you do.

  3. The original question had the dispatch to the background queue within addProcess, which makes more sense to me (keeps all the GCD stuff nicely encapsulated). You've updated your answer to say that you're invoking this via dispatch_async([self addProcess]) (by which I presume you meant to a global queue, not the main queue), which I'm less crazy about. I address both scenarios in my code samples below.

So, in short, if you're invoking this via [self addProcess] (without dispatching that, itself, to the background queue) I'd suggest:

- (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];
        });
    });
}

Or, alternatively,

- (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];
        });
    });
}

And if you're doing ...

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

then it's just:

- (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];
    });
}
于 2012-08-09T18:17:17.143 回答