Question

I've got a UICollectionView where a UIActivityIndicator is displayed in the cell before an image is loaded, which is then dismissed regardless of success or failure in the UIImageView+AFNetworking block. However sometimes I get leftover activity indicators which don't seem to hide or stop animating.

This is part of my cellForItemAtIndexPath:

- (UICollectionViewCell *)collectionView:(UICollectionView *)cv cellForItemAtIndexPath:(NSIndexPath *)indexPath {
...
NSURL *imageURL = [NSURL URLWithString:[tmpcamera objectForKey:@"url"]];
NSURLRequest *imageRequest = [NSURLRequest requestWithURL:imageURL cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10];

UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activityIndicator.hidesWhenStopped = YES;
activityIndicator.hidden = NO;
activityIndicator.frame = CGRectMake(0, 0, 130, 110);
activityIndicator.tag = 10;

[cell.imageView addSubview:activityIndicator];
[activityIndicator startAnimating];

__weak typeof(FavouriteCell) *weakImage = cell;
[cell.imageView setImageWithURLRequest:imageRequest
                      placeholderImage:[UIImage imageNamed:@"trans50.png"]
                               success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *i)
 {
     [activityIndicator stopAnimating];
     activityIndicator.hidden = YES;
     [activityIndicator removeFromSuperview];
     [weakImage.imageView setImage:i];

 }
                               failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error)
 {
     [activityIndicator stopAnimating];
     activityIndicator.hidden = YES;
     [activityIndicator removeFromSuperview];
     [weakImage.imageView setImage:[UIImage imageNamed:@"errorimage.png"]];
 }];
...
}

I'm unsure if this code is enough to debug what the issue is, but any ideas would be appreciated.

A sample screenshot of what I'm talking about is here:

sample

Was it helpful?

Solution

Since your cells may be recycled/reused before the image request has a chance to succeed or fail (via scrolling, for example), you can end up with an "orphaned" activity indicator in a cell.

Sequence of events:

  1. A cell loads, attempts to load the image and starts the activity indicator
  2. The user scrolls before the image loads. The cell is recycled.
  3. The cell is reused. A new activity indicator is added, and the previous image loading is aborted (so the previous success/failure blocks are never called). The old and new activity indicators are now both on the cell, with the old one still running.

Some suggestions to avoid this problem:

  1. Create a custom cell that includes the activity indicator.
  2. When creating the activity indicator assign a number to the indicator's tag property, then lookup to see if there's already an activity indicator via viewWithTag: when reusing a cell. If it already exists, use the existing one, otherwise, create a new one.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top