auto layout slow on iOS
auto layout slow on iOS
- Subject: auto layout slow on iOS
- From: Matt Neuburg <email@hidden>
- Date: Sun, 18 Nov 2012 19:50:18 -0800
It's a pity, but auto layout is slow on iOS. This emerges particularly in areas where it is possible to make a comparison between manual layout and auto layout. My example is a table with different heights for different rows.
The strategy for a table with different heights for different rows is to calculate all the row heights in advance, because the runtime will ask for all the row heights before displaying any cells. My cell has five UILabels. My old strategy was to work out the heights for these from top to bottom one row at a time, based on each row's contents, using sizeWithFont:constrainedToSize:. I use those results in both tableView:heightForRowAtIndexPath: and later in tableView:willDisplayCell: (where I actually lay out the labels in accordance with the measurements previously worked out). I've done it this way for years.
Since iOS 6 has auto layout, I thought I'd try using it. So I describe the cell layout in a nib using constraints. This makes tableView:heightForRowAtIndexPath: very simple, as there are no calculations or measurements to perform: I simply put the contents into each label and then ask the cell how tall it is, using systemLayoutSizeFittingSize:. And when the time comes to display the cell, there's no further layout to do (I can just eliminate tableView:willDisplayCell:) because auto layout does it all.
But the problem is that it's slow. It takes tableView:heightForRowAtIndexPath: about 2.5 seconds to calculate the heights for 127 rows, whereas the old way takes less than .5 second. And that's 2.5 seconds during which nothing happens, because the table doesn't appear until all the row heights have been supplied.
Just for the record, here's the simple and elegant but slow routine; I've put a comment where Instruments tells me the bottleneck is:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (!self.heights) {
// determine all heights once for all
NSMutableArray* marr = [NSMutableArray array];
NSArray* objects = [[UINib nibWithNibName:@"TrackCell6" bundle:nil]
instantiateWithOwner:nil options:nil];
UITableViewCell* cell = objects[0];
[self.titles enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[self setUpCell:cell forIndexPath:[NSIndexPath indexPathForRow:idx inSection:0]];
// the above call just puts actual text into all the labels
CGSize sz = [cell systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; // this is where the time is spent
[marr addObject: @(sz.height)];
}];
self.heights = marr;
}
return [self.heights[indexPath.row] floatValue];
}
m.
--
matt neuburg, phd = email@hidden, http://www.apeth.net/matt/
pantes anthropoi tou eidenai oregontai phusei
Programming iOS 5! http://shop.oreilly.com/product/0636920023562.do
RubyFrontier! http://www.apeth.com/RubyFrontierDocs/default.html
TidBITS, Mac news and reviews since 1990, http://www.tidbits.com
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden