I have a UITableViewCell that contains a UIScrollView. The UIScrollView contains a different number of UIImageViews for each row. Some rows have 5 images in the scroll view, some rows have 15 images in the scroll view. Since the number of UIImageViews in each row is different, I’m stuck allocating new UIImageViews when each row is drawn! This is obviously having a negative impact on scroll performance of my UITableView. How can I resolve this to improve UITableView scrolling?
Additionally, using Instruments’ Time Profiler, I’ve noticed that the method call [tableView dequeueReusableCellWithIdentifier:MyIdentifier] is abnormally slow. Does that help point to the problem?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = @"HuddleTableCell";
HuddleListItemTableViewCell *cellToReturn = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cellToReturn == nil) {
[[NSBundle mainBundle] loadNibNamed:@"HuddleListItemTableViewCell" owner:self options:nil];
cellToReturn = cell;
UILabel *badgeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
badgeLabel.font = [UIFont boldSystemFontOfSize:16];
badgeLabel.numberOfLines = 2;
badgeLabel.textAlignment = UITextAlignmentCenter;
badgeLabel.textColor = [UIColor whiteColor];
badgeLabel.backgroundColor = [UIColor clearColor];
[cellToReturn.attendee4Image addSubview:badgeLabel];
cellToReturn.othersOverlayLabel = badgeLabel;
[badgeLabel release];
cellToReturn.heartHolderView.layer.cornerRadius = 5;
cellToReturn.heartHolderView.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithRed:.29 green:.39 blue:.57 alpha:1.0] CGColor],(id)[[UIColor colorWithRed:.19 green:.22 blue:.36 alpha:1.0] CGColor], (id)[[UIColor colorWithRed:.102 green:.122 blue:.17 alpha:1.0] CGColor], nil];
cellToReturn.heartHolderView.colors = [NSArray arrayWithObjects:(id)[UIColorFromRGB(0x4A59A8) CGColor], nil];
cellToReturn.heartHolderView.layer.cornerRadius = 5.0;
UIView *polaroidView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 37, 39)];
polaroidView.layer.shadowColor = [UIColor blackColor].CGColor;
polaroidView.layer.shadowOpacity = 0.3;
polaroidView.layer.shadowRadius = 1;
polaroidView.layer.shadowOffset = CGSizeMake(5.0f, 5.0f);
polaroidView.backgroundColor = [UIColor whiteColor];
UIImageView *img = [[UIImageView alloc] initWithFrame:CGRectMake(4, 4, 29, 29)];
[polaroidView addSubview:img];
[cellToReturn.organizerImage addSubview:polaroidView];
cellToReturn.polaroidView = polaroidView;
cellToReturn.polaroidImageView = img;
[img release];
[polaroidView release];
cellToReturn.gradientView.colors = [NSArray arrayWithObjects:(id)[[UIColor whiteColor] CGColor],(id)[[UIColor colorWithRed:.96 green:.96 blue:.96 alpha:1.0] CGColor],(id)[[UIColor colorWithRed:.85 green:.85 blue:.85 alpha:1.0] CGColor], nil];
cellToReturn.votingTimerLabel.textColor = UIColorFromRGB(0x616163);
cellToReturn.eventDateLabel.textColor = UIColorFromRGB(0x616163);
cellToReturn.eventNameLabel.textColor = UIColorFromRGB(0x616163);
cellToReturn.numInviteesLabel.textColor = UIColorFromRGB(0x616163);
cellToReturn.numVotesLabel.textColor = UIColorFromRGB(0x616163);
self.cell = nil;
}
NSString *organizerFbId = [[self.huddleList objectAtIndex:indexPath.row]objectForKey:@"userId"];
[cellToReturn.polaroidImageView setImageWithURL:[self.organizerImageUrls objectForKey:organizerFbId] placeholderImage:self.placeholderImage];
[[cellToReturn.imageScrollViewHolder subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
if ([self.avatarScrollViews objectForKey:[[self.huddleList objectAtIndex:indexPath.row]objectForKey:@"id"]]) {
[cellToReturn.imageScrollViewHolder addSubview:[self.avatarScrollViews objectForKey:[[self.huddleList objectAtIndex:indexPath.row]objectForKey:@"id"]]];
} else {
UIScrollView *tempImageScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 200, 46)];
tempImageScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
NSArray *fbUids = [[self.huddleList objectAtIndex:indexPath.row] objectForKey:@"facebookInvitees"];
int i=0;
for (i=0;i < [fbUids count];i++) {
UIView *polaroidView = [[[UIView alloc] initWithFrame:CGRectMake((i * 45) + (3 * i), 0, 37, 39)] autorelease];
polaroidView.layer.shadowColor = [UIColor blackColor].CGColor;
polaroidView.layer.shadowOpacity = 0.3;
polaroidView.layer.shadowRadius = 1;
polaroidView.layer.shadowOffset = CGSizeMake(5.0f, 5.0f);
polaroidView.backgroundColor = [UIColor whiteColor];
UIImageView *img = [[[UIImageView alloc] initWithFrame:CGRectMake(4, 4, 29, 29)] autorelease];
[img setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://graph.facebook.com/%@/picture", [fbUids objectAtIndex:i]]] placeholderImage:self.placeholderImage];
[polaroidView addSubview:img];
[tempImageScrollView addSubview:polaroidView];
}
[tempImageScrollView setContentSize:CGSizeMake((i*45) + (3 * i), 46)];
[self.avatarScrollViews setObject:tempImageScrollView forKey:[[self.huddleList objectAtIndex:indexPath.row]objectForKey:@"id"]];
[cellToReturn.imageScrollViewHolder addSubview:tempImageScrollView];
[tempImageScrollView release];
}
return cellToReturn;
}
Even there was a fixed number of images in each cell’s scroller, you’d be stuck allocating them as the cells are dequeued and reused. The way to get speed is to take up some more space, by keeping the cells’ subviews in an array outside of the table.
Create another array that has the same count as your huddleList array. Fill that array with UIScrollViews containing the imageViews. All that code in your cellForRowAtIndexPath method can move to the initialization method for the new array and get replaced by a few simple lines:
Don’t forget to release the cachedScrollViews on memory warning