Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

show activity indicator while loading ViewController

Tags:

iphone

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?

like image 468
Crystal Avatar asked Jan 15 '23 11:01

Crystal


1 Answers

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.

like image 101
Tom Hamming Avatar answered Jan 28 '23 13:01

Tom Hamming