1337code 1337code - 29 days ago 7
iOS Question

UIActivity indicator in custom cell in storyboard

I have added an IBOutlet of UIActivityIndicator to custom cell but it doesn't show on every cell, just on first 2-3 and then nothing.
Another thing, when I scroll the table and get back too first 3 cells, UIActivityIndicator disappears from these cells too...

Code:

Cell.h

@interface Cell : UITableViewCell

@property (strong, nonatomic) IBOutlet UIImageView *image;
@property (strong, nonatomic) IBOutlet UILabel *label;
@property (strong, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;

@end


Cell.m

@implementation Cell

- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
// change to our custom selected background view
}
return self;
}

@end


In storyboard UIactivityIndicator is set to:
Behavior:
- Animating

for testing purposes...

and:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"CustomCell";
Cell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

// load the image for this cell
Wallpaper *wallpaper = [xmlParser.wallpapers objectAtIndex:indexPath.row];

cell.label.text = wallpaper.title;
NSString *imageToLoad = wallpaper.thumbnail;

[cell.image setImageWithURL:[NSURL URLWithString:imageToLoad] placeholderImage:nil options:SDWebImageProgressiveDownload progress:^(NSUInteger receivedSize, long long expectedSize)
{

}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType)
{
//[cell.activityIndicator stopAnimating];
}];

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(tapped:)];
[cell.image addGestureRecognizer:tap];
[cell.image setTag:indexPath.row];

CALayer * l = [cell.image layer];
[l setMasksToBounds:YES];
[l setCornerRadius:5.0];
cell.layer.cornerRadius = 7.0;


return cell;
}

Rob Rob
Answer Source
  1. If you comment out that entire piece of code where you're doing the setImageWithURL, do you get your animated activity indicator successfully on all of the rows of your table? Let's first make sure your UIActivityIndicatorView is working correctly. If it works when you comment out setImageWithURL, then the problem clearly rests there. If it doesn't work, even when you disable setImageWithURL, then you have a more fundamental issue. Let's make sure you are starting the activity indicator successfully. I gather that you're turning it on in IB, but I'd really suggest manually turning it on (when appropriate) in cellForRowAtIndexPath, and not relying upon it being started for you.

  2. In your completed block, you really should be checking to make sure the cell in question is still on screen and hasn't been dequeued and reused (e.g. invoking cell = [tableView cellForRowAtIndexPath:indexPath] and confirm a non-nil value) because I'm assuming your setImageWithURL is operating asynchronously. (NB: This UITableView instance method, cellForRowAtIndexPath, should not be confused with the similarly named UITableViewController method.) This sort of logic about assuming the cell is still on screen can be problematic whenever you do async operations on tableview cells. When I hear about the fact that some asynchronous update isn't updating properly, I worry about dequeued cells. (See my point #3 on this Stack Overflow Answer for an example of how to check to see if the cell is still visible; It's a slightly different answer, but gives you an example of the sort of issue you need to be thinking about.)

  3. Unrelated, but I wouldn't be adding the UITapGestureRecognizer every time. Aren't you risking a cell that's been dequeued and reused a dozen times having a dozen tap gesture recognizers? Better to do it in your UITableViewCell subclass. I generally do it in layoutSubviews (won't work if you try to do it in your init methods because the imageview won't exist yet).