Search code examples
iosuitableviewmemory-efficient

Customize a simple UITableViewCell efficiently


I would like to customize a simple UITableViewCell so that I run the customization only once and add values (e.g., cell title) later. My app's cell is more complex - it has subviews and uses auto layout; however, a simple example, I believe, will help in focusing on the objective.

I am using iOS 8, Xcode 6.X, Objective-C and Nibs (no storyboard) to keep it simple. I have not created a custom class for UITableViewCell. Instead, I have the following code:

- (void)viewDidLoad {
    [super viewDidLoad];
    //[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;  //FIXED VALUE FOR EXAMPLE'S SAKE
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 3;  //FIXED VALUE FOR EXAMPLE'S SAKE
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    NSLog(@"tableView:cellForRowAtIndexPath:");

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    //UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    if (cell == nil) {

        NSLog(@"cell == nil");

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];

        //CUSTOMIZING CELL THAT I WANT TO RUN ONLY ONCE
        cell.backgroundColor = [UIColor redColor];
    }

    NSArray *numbersArray = @[@1,@2,@3];
    cell.textLabel.text = [NSString stringWithFormat:@"%@", numbersArray[indexPath.row]];

    return cell;
}

Which outputs:

tableView:cellForRowAtIndexPath:
cell == nil
tableView:cellForRowAtIndexPath:
cell == nil
tableView:cellForRowAtIndexPath:
cell == nil

FIRST QUESTION: Why is cell == nil run 3 times? It seems wasteful to run the customization code cell.backgroundColor = [UIColor redColor]; 3 times.

Now, when I enable:

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];

And use:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

Instead of:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

I get the output:

tableView:cellForRowAtIndexPath:
tableView:cellForRowAtIndexPath:
tableView:cellForRowAtIndexPath:

SECOND QUESTION: Why isn't cell == nil run at all?

FINAL QUESTIONS: How can I make cell == nil run only once so that I format the UITableViewCell only once? Is there a better way to customize a simple cell, running the customization code only once?


Solution

  • Why is cell == nil run 3 times? It seems wasteful to run the customization code cell.backgroundColor = [UIColor redColor]; 3 times.

    The table view most likely displays three cells at once, hence requiring three distinct cell objects.

    Why isn't cell == nil run at all?

    The documentation states that -dequeueReusableCellWithIdentifier:forIndexPath: always returns a valid cell if you registered the identifier previously. It basically takes care of checking if a new cell is required for you.

    How can I make cell == nil run only once so that I format the UITableViewCell only once?

    You don't. You will have to customize every single instance. I would recommend to use a custom subclass though, rather then messing with UITableViewCell from the outside.