Question

I work on an application with some heavy tasks (Ajax requests and JSON parsing) and I'd like to use UIIndicatorViews to show the device is busy.

Let's say I start from a "source" view and want to show an indicator before going on a "target" view after having loaded my data.

My approach: starting the indicator in source.didSelectRowAtPath, loading the data in target.viewDidLoad, stopping the indicator in source.viewDidDisappear.

Problem: the indicator animates only after a delay.

"Source.m"

- (void)startIndicator {
   indicator.hidden = NO;
   [indicator startAnimating];
}

- (void)stopIndicator {
   indicator.hidden = YES;
   [indicator stopAnimating];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
   [self stopIndicator];
}

- (void)viewDidDisappear:(BOOL)animated {
   [self stopIndicator];
   [super viewDidDisappear:animated];
}

"Target"

- (void)viewDidLoad {
   [super viewDidLoad];
   [self longLoadingMethod];
}
Was it helpful?

Solution

I just had to use detachNewThreadSelector to start the indicator in an other thread!

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
   [NSThread detachNewThreadSelector:@selector(stopIndicator)
                            toTarget:self
                          withObject:nil];
   // instead of [self stopIndicator];
}

Edit

And to start Indicator:

[NSThread detachNewThreadSelector:@selector(startIndicator)
                            toTarget:self
                          withObject:nil];

// instead of [self startIndicator];

OTHER TIPS

Why not trigger the loading on the user action (the action that would trigger the transition)?

  1. User taps the UIResponder Loading begins in background (current VC is a delegate or use a completion block)
  2. Activity indicator activated (make sure this happens on the main thread)
  3. When loading completes, hide activity indicator, transition views

This can all be done without messing around with NSThread -- also if you fail to load perhaps you don't want to transition views (maybe to show an alert instead?).

EDIT

You could do something like this:

- (IBAction)didTapLoadResource:(id)sender
{
    [self startIndicator];
    [NSURLConnection sendAsynchronousRequest:self.remoteResource queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
        [self stopIndicator];
        if (error)
        {
            [self showFailureAlert];
        }
        else
        {
            [self presentViewController:self.loadedVC animated:YES completion:nil];
        }
    }];
}

Note that this code was written in the browser and may need editing.

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