15

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.

Jay Bhalani
  • 4,142
  • 8
  • 37
  • 50
Eytan
  • 1,825
  • 17
  • 24
  • Show us your nib loading code. – rob mayoff Dec 13 '11 at 06:23
  • Thank you for taking a look @robmayoff. I updated the question to include my code for loading the nib. – Eytan Dec 13 '11 at 06:35
  • Interesting find - would you be able to run the experiment again using storyboards and prototype cells, where the table view does all the nib loading in the background? – jrturton Dec 13 '11 at 07:03
  • I was not aware that UIKit is thread safe. Has anyone else tried loading nib files in the background? – Eytan Dec 13 '11 at 15:43

4 Answers4

13

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.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • Wow that helped a lot! The average running time (for the duration of theists) dropped from around 300ms to 90ms when loading from the NIB using the technique you mentioned. Loading programmatically, had an average running time of around 50 ms. – Eytan Dec 13 '11 at 07:03
5

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.

Robotic Cat
  • 5,899
  • 4
  • 41
  • 58
  • This is essentially the same thing as using a UINib as I am in my second edit. I can't imagine it would be any faster but it certainly is nicer to program. I'm going to do that from now on - Thanks! – Eytan Dec 14 '11 at 00:27
  • what is "self.reuseCustomCell" referring to? – zakdances May 30 '12 at 17:16
  • self.reuseCustomCell is a property along the lines of @property (nonatomic, strong) id reuseCustomCell; – Robotic Cat May 30 '12 at 18:03
2

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.

Rhythmic Fistman
  • 34,352
  • 5
  • 87
  • 159
  • I'm going to try the keyed archiving method tomorrow morning. You touch on a good point regarding the frame rate. The reason I started analyzing the fastest method to UITableViewCells is because my orientation change animation is extremely slow. During this animation I transition between two UITableViewControllers and the time profiler highlighted the heaviest stack trace occurs when I load the UITableViewCells. Do you have any suggestions on how to speed up the frame rate? – Eytan Dec 13 '11 at 08:04
0

It's possible to reuse the uitableviewcell nibs which are once loaded and then they go out of the view. Read the following:

iPhone - What are reuseIdentifiers (UITableViewCell)?

Community
  • 1
  • 1
Sanjay Chaudhry
  • 3,181
  • 1
  • 22
  • 31
  • You have a good point Sanjay. A few lines above my nib loading code I check for cells with the appropriate reuse identifier. – Eytan Dec 13 '11 at 18:37