Get tableView:heightForRowAtIndexPath: to happen after tableView:cellForRowAtIndexPath:?

cocoa-touch, iphone, uitableview

Solution

Gonna answer my own question here:

Originally I was pretty sure that the height calculations were tied to the `tableView:cellForRowAtIndexPath:` method, and couldn't be moved elsewhere. With a bunch of restructuring, though, I was able to get that stuff out of there and into `tableView:heightForRowAtIndexPath:`, which solves everything.

For anyone else who's trying to get auto-height-adjusted cells to work, here's some code that might help:

// Inside tableView:cellForRowAtIndexPath:
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = self.numberOfTextRows;
// numberOfTextRows is an integer, declared in the class

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    CGSize theSize = [theObject.theStringToDisplay sizeWithFont:[UIFont systemFontOfSize:18.0f] constrainedToSize:CGSizeMake(265.0f, 9999.0f) lineBreakMode:UILineBreakModeWordWrap];
    // This gets the size of the rectangle needed to draw a multi-line string
    self.numberOfTextRows = round(theSize.height / 18);
    // 18 is the size of the font used in the text label
    // This will give us the number of lines in the multi-line string

    if ((indexPath.section == FIXED_HEIGHT_SECTION) || (self.numberOfTextRows < 2)) {
        return 44;
        // 44 is the default row height; use it for empty or one-line cells (or in other table sections)
    } else {
        return theSize.height + 16;
        // 16 seems to provide a decent space above/below; tweak to taste
    }
}

If you can think of a more accurate way to calculate the proper cell height, I'm all ears. :)

Problem

I've got some UITableViewCells that need to change their height depending on the length of the strings inside. I'm calculating the necessary height inside `tableView:cellForRowAtIndexPath:`, and then storing it in a variable (`self.specialRowHeight`). Then I've got: ``` - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == SPECIAL_SECTION) { return self.specialRowHeight; } else { return 44; } } ``` Except that seems to be getting called before the `tableView:cellForRowAtIndexPath:` bit, so it's always zero. Is there a way around this, or perhaps a different way to do it? Thanks!

Original source