0

I am having a small issue with MBProgressHUD in my app.

Basically I am using it in the simplest way I can find to do it:

[MBProgressHUD showHUDAddedTo:self.view animated:YES];
[self performSelector:@selector(save) withObject:nil afterDelay:0.001];
[self refreshView];

The method refreshView has this line at the end of it's execution:

[MBProgressHUD hideHUDForView:self.view animated:YES];

The MBProgress shows up exactly how it should, but for the last half(ish) of it's duration fades to a barely visible state, making it appear as though the methods have finished executing before they actually finish.

Any ideas on what might be going wrong here?

Thanks a lot!

Dream Lane
  • 1,282
  • 5
  • 16
  • 27

2 Answers2

2

It's hard to give a precise solution without seeing more of your code. But basically the problem probably has something to do with the fact that you are calling [self refreshView] and therefore [MBProgressHUD hideHUDForView:self.view animated:YES] before your save method is even called. Why don't you hide the HUD at the end of the save method, or call save directly rather than after a delay. I'm not sure why you have to perform the save after a delay.

UIAdam
  • 5,303
  • 1
  • 27
  • 23
  • I don't fully understand it myself, however this question here: http://stackoverflow.com/questions/5685331/run-mbprogresshud-in-another-thread led me to this configuration of code I have... If i do [self save]; instead of the performSelector code, then the Screen freezes for a second, and then flashes the progressHUD. – Dream Lane Jan 31 '12 at 01:35
  • 1
    @UIAdam: you have to perform the save after a delay, please see my answer for an explanation. – mvds Jan 31 '12 at 01:45
  • Sure, makes perfect sense. I forgot that the HUD would need a chance to animate in before you try to save. – UIAdam Jan 31 '12 at 02:11
2

The concept you need to understand is that of the run loop. The run loop is the internal loop in your program that handles incoming events, timers, networking, etc. (It is provided and run by the system so you don't actually see this loop in your code.)

With this line:

[self performSelector:@selector(save) withObject:nil afterDelay:0.001];

you schedule the -save action to run after 1 ms. (or later, if the main thread is busy doing something else)

After scheduling this -save (so not after running it) you call your refreshView which hides the HUD.

So what actually happens is that you show and hide the HUD in one go. So you see something like the combined animation of showing and hiding it. Independently, your -save method is called.

Contrary to what UIAdam suggests, you do need the performSelector:afterDelay: because you need to give the run loop some time to breathe and display your eye candy on the screen. Changes to the user interface do not happen immediately, but only as the program returns to the run loop.

The fix is therefore to take this line:

[self refreshView];

and move it to the end of your -save method.

mvds
  • 45,755
  • 8
  • 102
  • 111
  • I appreciate the simple explanation of the run loop. It's something I've struggled to get a grasp of for the passed couple days. You are exactly right, moving the refresh method to the end of my save method solved the issue! Thanks! – Dream Lane Jan 31 '12 at 02:04