Question

I have a method myButtonAction which performs some heavy calculations, which I need to run on a background thread, while I am loading a view indicating "Task progress" in the main thread. As soon as the, background thread completes executing the method, I need to remove the "task progress" view and load another view in the main thread.

[self performSelectorInBackground:@selector(myButtonAction) withObject:nil];
[self performSelectorOnMainThread:@selector(LoadView) withObject:nil waitUntilDone:YES];

The problem I am facing is that, before myButtonAction completes execution, the LoadView completes its execution. How can I make sure that LoadView starts execution only after myButtonAction completes its execution.

Note: myButtonAction has its method definition in another class.

Was it helpful?

Solution

Use Grand Central Dispatch:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self myButtonAction];
    dispatch_async(dispatch_get_main_queue(), ^{
        [self LoadView];
    });
});

Or, if you want to stay with performSelector methods:

[self performSelectorInBackground:@selector(loadViewAfterMyButtonAction) withObject:nil];

where

- (void)loadViewAfterMyButtonAction
{
    [self myButtonAction];
    [self performSelectorOnMainThread:@selector(LoadView) withObject:nil waitUntilDone:YES];
}

OTHER TIPS

You need to do following -

[self performSelectorInBackground:@selector(myButtonAction) withObject:nil];

- (void)myButtonAction {
    //Perform all the background task

   //Now switch to main thread with all the updated data
    [self performSelectorOnMainThread:@selector(LoadView) withObject:nil waitUntilDone:YES];
}

EDIT - Then you can try -

[self performSelectorInBackground:@selector(buttonActionInBackground) withObject:nil];

 - (void)buttonActionInBackground {
       [self myButtonAction];

       //Now switch to main thread with all the updated data
    [self performSelectorOnMainThread:@selector(LoadView) withObject:nil waitUntilDone:YES];
  }

Now you don't need to change myButtonAction.

I take it that this code gets called at the end of myButtonAction:

[self performSelectorOnMainThread:@selector(LoadView) withObject:nil waitUntilDone:YES];

now no wonder that LoadView finishes before myButtonAction finishes, because you said it to wait until it's done with "waitUntilDone:YES". Call it at the end with waitUntilDone:NO.

For simple solutions to this kind of problems take a look at putting selector calls into the main run loop using [self performSelector:@selector(sel) withObject:obj afterDelay:0.0] or NSTimer - for example if you want to wait until UI updates are finished.

I use a Semaphore Design Pattern for these purposes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top