Time profiler shows the most time consuming operation in my app is loading UITableViewCells
from nib files. The most expensive of which involves loading a UITableViewCell
with a 4KB image.
I am loading the UITableViewCell
from the nib with the following code:
[[NSBundle mainBundle] loadNibNamed:@"UITableViewCellPortrait" owner:self options:NULL];
cell = portraitCell;
self.portraitCell = nil;
Has anyone compared the difference between creating a view programmatically or loading a UITableViewCell
from a nib?
EDIT:
I compared the time profile of repeated runs of loading the UITableViewCell
from a nib and creating the view programmatically. My test involved alternating between two UITableViews
about 10 times in the span of 3-5 seconds. In each test, loading the UITableViewCell
programmatically was substantially faster, between 2x to 6x faster.
Can anyone corroborate these results?
EDIT: I updated the nib loading code to only load the nib file once and use a cached version for subsequent calls.
if (self.UITableViewPortaitNib == nil) {
self.UITableViewPortaitNib = [UINib nibWithNibName:@"UITableViewCellPortrait" bundle:[NSBundle mainBundle]];
}
self.UITableViewPortaitNib instantiateWithOwner:self options:NULL];
cell = portraitCell;
self.portraitCell = nil;
I also used the automation instrument to create more consistent runs and the results still suggest loading UITableViewCells
programmatically is faster than loading UITableViewCells
for a nib. The average running time for loading UITableViewCells
from a nib was around 90ms, while the average running time for creating the UITableViewCell
programmatically was 50ms.
Try creating a UINib
object once and then sending it instantiateWithOwner:options:
each time you need to create a new cell. From the UINib Class Reference:
For example, if your table view uses a nib file to instantiate table view cells, caching the nib in a
UINib
object can provide a significant performance improvement.
In iOS 5 and mentioned in the WWDC 2011 videos, there is a newer method that uses UINib. You register your nib in your viewDidLoad:
method and then simplify the code in the tableView:cellForRowAtIndexPath:
method. This may speed things up for you (but I've never performed any comparison timings).
Example:
In your viewDidLoad:
register the nib and retain a reference to it:
NSString *myIdentifier = @"ReusableCustomCell";
[self.reuseCustomCell registerNib:[UINib nibWithNibName:@"ReusableCustomCell" bundle:nil] forCellReuseIdentifier:myIdentifier];
In your tableView:cellForRowAtIndexPath:
method just ask for the cell (no need to check for nil as it is guaranteed to return a cell under iOS5) and configure the cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *myIdentifier = @"ReusableCustomCell";
ReusableCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:myIdentifier];
// Your configuration code goes here
cell.nameLabel.text = @"some text";
// ....
return cell;
}
Code not tested. I'd be interested if this was any faster than using UINib alone.
I load the nib cell (cellTemplate
) once and duplicate it as needed, so in a sense this approach is both programmatic and nib based.
Duplicating was more complicated than I expected as mutableCopy
didn't work. An NSKeyedArchiver
roundtrip did, however:
NSData* cellData = [NSKeyedArchiver archivedDataWithRootObject:cellTemplate];
cell = [NSKeyedUnarchiver unarchiveObjectWithData:cellData];
In fact if you're going for raw, blazing, pedal-to-the-metal speed, even the archived template can be calculated once and cached.
But shouldn't you be measuring frame rate? In that case the UIView's complexity comes into play too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With