4

I have a ViewController that takes time to load its views. When I run Instruments, I see from the home screen, if I tap on the icon that pushes that view controller onto the stack, it's half laying out the views, and half getting the data for the views. I tried adding an activity indicator to display on the home screen over the button when the button is pressed to push the LongRunningViewController onto the stack. So I basically do this:

- (IBAction)puzzleView:(id)sender {
    dispatch_async(dispatch_get_main_queue(), ^{
        [self.activityIndicator startAnimating];
    });

    PuzzleViewController *detailViewController = [[[PuzzleViewController alloc] init] autorelease];
    [self.navigationController pushViewController:detailViewController animated:YES];
    [self.activityIndicator stopAnimating];
}

The home screen lags while pressing the button, and then loads the view. I'm trying to show the activity indicator while the other screen is preparing to be pushed (or at least that's the way I think it works). The activity indicator does not show however. I'm wondering if this can be done? Or do other apps push their ViewController, and then on that screen, they have the activity indicators showing the loading of their different resources?

2
  • Can you clarify what your question is? Commented Sep 24, 2012 at 21:41
  • @Mr. Jefferson Sorry about that, hit Submit too fast! Commented Sep 24, 2012 at 21:43

1 Answer 1

9

When you say that it takes time to get the data for the views, I assume you mean that the PuzzleViewController does something non-trivial somewhere like viewDidLoad.

So let's say it is in viewDidLoad. Then you can do this:

-(void)viewDidLoad
{
  [self.activityIndicator startAnimating];
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
    {
         //do something expensive
         [self doSomethingExpensive];

         //dispatch back to the main (UI) thread to stop the activity indicator
         dispatch_async(dispatch_get_main_queue(), ^
         {
            [self.activityIndicator stopAnimating];
         });
    });
}

This will mean that the expensive operation will be put on a background thread and won't block the loading/showing of the view controller.

This approach is showing the requested view immediately when the user pushes the button, and showing progress on that screen. I think it's more common this way than to show an activity view while loading contents before presenting the view. This also buys you a little bit more time; your long operation can be running in the background during the transition animation!

The reason your activity view isn't showing the way you're doing it is that you're doing it all on the UI thread; using dispatch_async to the main queue from the main queue won't accomplish anything because your block won't have a chance to run until the run loop completes.

Sign up to request clarification or add additional context in comments.

2 Comments

So in that scenario, the activity indicator is on the page being loaded, not on the ViewController before right?
@Crystal - If your operation is long enough (takes a second or more or so after the transition animation) and its completion is essential to showing the view controller, you should consider using MBProgressHUD.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.