UITableView dynamic cell heights only correct after some scrolling

blackp picture blackp · Sep 22, 2014 · Viewed 62.3k times · Source

I have a UITableView with a custom UITableViewCell defined in a storyboard using auto layout. The cell has several multiline UILabels.

The UITableView appears to properly calculate cell heights, but for the first few cells that height isn't properly divided between the labels. After scrolling a bit, everything works as expected (even the cells that were initially incorrect).

- (void)viewDidLoad {
    [super viewDidLoad]
    // ...
    self.tableView.rowHeight = UITableViewAutomaticDimension;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
    // ...
    // Set label.text for variable length string.
    return cell;
}

Is there anything that I might be missing, that is causing auto layout not to be able to do its job the first few times?

I've created a sample project which demonstrates this behaviour.

Sample project: Top of table view from sample project on first load. Sample project: Same cells after scrolling down and back up.

Answer

rintaro picture rintaro · Sep 22, 2014

I don't know this is clearly documented or not, but adding [cell layoutIfNeeded] before returning cell solves your problem.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
    NSUInteger n1 = firstLabelWordCount[indexPath.row];
    NSUInteger n2 = secondLabelWordCount[indexPath.row];
    [cell setNumberOfWordsForFirstLabel:n1 secondLabel:n2];

    [cell layoutIfNeeded]; // <- added

    return cell;
}