Reputation: 2941
I use a table view where I override heightForRowAtIndexPath
. When I run the Xcode profiler I found the following:
I want to calculate the height based one object's property. I use the same table view for two kind of objects, User
and Post
. My implementation currently looks like this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *text;
Post *cellPost;
User *cellUser;
if (_pageType == FOLLOWERS || _pageType == FOLLOWING) {
cellUser = [self.users objectAtIndex:indexPath.row];
text = cellUser.userDescription.text;
if (text == nil) {
return 70;
}
} else {
cellPost = [self.fetchedResultsController objectAtIndexPath:indexPath];
text = cellPost.text;
}
CGSize boundingSize = CGSizeMake(245, CGFLOAT_MAX);
CGSize requiredSize = [text sizeWithFont:[UIFont fontWithName:@"TisaMobiPro" size:15]
constrainedToSize:boundingSize
lineBreakMode:NSLineBreakByWordWrapping];
CGFloat textHeight = requiredSize.height;
CGFloat cellHeight = textHeight + 40;
if ([cellPost.text isEqualToString:self.post.text]) {
cellHeight += 44;
if (cellHeight < 114) {
cellHeight = 114;
}
} else {
if (cellHeight < 70) {
cellHeight = 70;
}
}
if (cellPost.repostedBy != nil && cellPost.youReposted.boolValue == NO && _pageType != CONVERSATION) {
cellHeight += 27;
}
return cellHeight;
}
If I remove most of the code and only have, e.g. return 100
the tableView's scrolling performance is much improved. Can you spot or give suggestions on something in my implantation that could cause this performance issue?
Upvotes: 0
Views: 637
Reputation: 112855
If you are targeting iOS7 you can use the NSTableView
property: estimatedRowHeight
.
From the Apple docs:
Providing a nonnegative estimate of the height of rows can improve the performance of loading the table view. If the table contains variable height rows, it might be expensive to calculate all their heights when the table loads. Using estimation allows you to defer some of the cost of geometry calculation from load time to scrolling time.
Also:
Every time a table view is displayed, it calls tableView:heightForRowAtIndexPath: on the delegate for each of its rows
If you have to use tableView:heightForRowAtIndexPath:
cache the heights as @Waine suggests.
Upvotes: 1
Reputation: 26383
Heights are calculated before the – tableView:cellForRowAtIndexPath:
is called and for all the number of cells.
If you are deploying on iOS7 you can use the - tableView:estimatedHeightForRowAtIndexPath:
, using that method you can defer this calculation while scrolling the tableview. That means that the method tableView:heightForRowAtIndexPath:
is called basically when a cell is displayed. The estimation could be a fixed number close to the average of your TVC or based on some math faster than the one that you implemented.
Thanks to the estimation the TV can set its content size an scroll bar height and doesn't need to calculate each height for 100 of rows in one shot. The payback could be a lag during scrolling because the TV is calculating the actual row height.
Upvotes: 1