Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying UI element on main dispatch queue causes element to appear then disappear

I want to display a progress HUD right before starting a long task, and dismiss it once the task is done. Right now the UI freezes for some time, then the HUD shows for a second before disappearing. After another 4-5 seconds the task is finished and it displays its results, but the progress HUD is already gone.

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

I use SVProgressHUD for the progress HUD. I am calling the method addProcess using dispatch_async()

If I use the old +[NSThread detach...], it's working flawlessly, but I don't want to use it anymore.

like image 816
DevFly Avatar asked Nov 17 '25 20:11

DevFly


1 Answers

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];
    });
}
like image 153
Rob Avatar answered Nov 20 '25 13:11

Rob



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!