views:

43

answers:

2

I downloaded some code from http://github.com/matej/MBProgressHUD to show a progress meter when doing something.

This is the code that makes the progress meter pop up.

[HUD showWhileExecuting:@selector(myTask) onTarget:self withObject:nil animated:YES];

This will show a progress meter while the method myTask is running.

The strange thing is that it will also allow program execution to continue below this line while myTask is running. This is not the behavior I want. I want the progress meter to show while myTask is running, and only after myTask finishes running do I want program execution to continue below this line.

This is the code for the showWhileExecuting method.

- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated {

    methodForExecution = method;
    targetForExecution = [target retain];
    objectForExecution = [object retain];

    // Launch execution in new thread
 taskInProgress = YES;
    [NSThread detachNewThreadSelector:@selector(launchExecution) toTarget:self withObject:nil];

 // Show HUD view
 [self show:animated];
}

In order to get the behavior I want, should I edit this code, or do something else?

I tried to get around this problem by setting a bool value before calling this method which causes program execution to be stuck in a while loop immediately after until the bool value is changed at the end of myTask. This works, but for some reason it causes the meter to only show up for an instant at the end, and not throughout like it's supposed to. Why is that?

+1  A: 

The method you are calling is running your task on a new thread.

Your while loop method is not working because the the UI display update is done on the main thread. While you are in the while loop you block the main thread.

I suggest that you move the code you want to run after the task completes to a new method. Then, at the end of your task, call this method. (Or alternatively, have it send a notification, or some other signal.)

Also, look up the documentation about threading and run loops, it's important to understand this topic.

invariant
+1  A: 

It's because you are fundamentally misunderstanding the way views are drawn in iOS.

When the state of a view changes, the effects that the change of state would have are not shown on the screen immediately. What really happens is that the view that will change is marked as invalid and placed on a queue of things that need redrawing. Then, when the processing of the current event finishes, all the queued changes are processed.

So with your while loop in place, the HUD view will only get shown when your threaded task has finished. Of course, at that point, it's time to stop showing the view.

What you'll need to do is move the processing you want to delay until after the thread has finished into its own method. Then, at the end of the thread, you can use -performSelectorOnMainThread:... to kick off the remaining processing.

If there are user interface elements you want disabled, you will need some extra state so they know they are disabled.

JeremyP