UIActivityIndicatorView does not show

Pheepster picture Pheepster · Oct 23, 2013 · Viewed 14.8k times · Source

I have an app with a table view controller in which a user selects a US state, a web service is called and data is displayed for that state in the destination table view controller. Since the web service can take some time to complete I want an activity indicator. Since there will be no temporary data to display, I need this to be processed synchronously. So my task is pretty simple: start the activity indicator, call the web service, and after it completes, stop the activity indicator.

I am obviously doing something wrong and no activity indicator ever displays.

Here is the code from my destination table view controller's viewDidAppear method:

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    [self.tableView bringSubviewToFront:spinner];
    spinner.hidesWhenStopped = YES;
    spinner.hidden = NO;
    [spinner startAnimating];
    stateGauges = [[GaugeList alloc] initWithStateIdentifier:stateIdentifier andType:nil];
    [self.tableView reloadData];
    [spinner stopAnimating];
}

Header:

@property (strong, nonatomic) UIActivityIndicatorView *spinner;

GaugeList is the object which makes the web service call.

Can someone tell me how to get an activity indicator view to appear? Thanks!

Answer

Sviatoslav Yakymiv picture Sviatoslav Yakymiv · Oct 23, 2013

You forgot to add spinner on table view. Your code should look as follows:

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    spiner.center = //set some center
    [self.tableView addSubview: spinner];
    [self.tableView bringSubviewToFront:spinner];
    spinner.hidesWhenStopped = YES;
    spinner.hidden = NO;
    [spinner startAnimating];
    stateGauges = [[GaugeList alloc] initWithStateIdentifier:stateIdentifier andType:nil];
    [self.tableView reloadData];
    [spinner stopAnimating];
}

Also you send requests to a web service in main thread. This is bad practice. I would suggest something like following:

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    spiner.center = //set some center
    [self.tableView addSubview: spinner];
    [self.tableView bringSubviewToFront:spinner];
    spinner.hidesWhenStopped = YES;
    spinner.hidden = NO;
    [spinner startAnimating];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        stateGauges = [[GaugeList alloc] initWithStateIdentifier:stateIdentifier andType:nil];
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.tableView reloadData];
            [spinner stopAnimating];
        });
    });
}