4

Example project: http://cl.ly/2j0A1J203f3h

I'm trying to use Auto Layout to dynamically determine each cell's height so some cell's can hold more content than others. To do this I'm using this Stackoverflow answer and the accompanying GitHub example.

I have a UITableViewCell subclass called CSPostCell that I created in the Storyboard and put a UILabel in with a maximum of 5 lines of text in the label.

Just for example purposes, I'm only having two cells in the table and as such two different pieces of text for the labels (one's longer) which is set up in cellForRowAtIndexPath::

- (CSPostCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CSPostCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SelfPostCell" forIndexPath:indexPath];
    cell.postTitle.text = indexPath.row == 0 ? @"Short title" : @"Long long long title. Holy crap this is one long title. When does it end? Oh right now.";
    [cell setNeedsUpdateConstraints];

    return cell;
}

I then return the height of each cell as such:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    CSPostCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SelfPostCell"];

    cell.postTitle.text = indexPath.row == 0 ? @"Short title" : @"Long long long title. Holy crap this is one long title. When does it end? Oh right now.";
    cell.postTitle.preferredMaxLayoutWidth = tableView.bounds.size.width - 40;

    [cell setNeedsUpdateConstraints];
    [cell updateConstraintsIfNeeded];
    [cell.contentView setNeedsLayout];
    [cell.contentView layoutIfNeeded];

    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    return height;
}

Which is more or less an exact copy from the GitHub repo example.

However, when I run the app in the simulator, it doesn't quite work as it should. The heights are dynamic and adjust for longer pieces of text, but not enough that the text doesn't get cut off. See the image below:

enter image description here

In that above case the second cell's label should show another line to finish off the text, but it gets cut off.

Why is it not showing all the text?

Community
  • 1
  • 1
Doug Smith
  • 29,668
  • 57
  • 204
  • 388

1 Answers1

3

This simplified code worked well for me, with just one slight fudge of 2 points. All the calls to updateConstraints seem to be unnecessary. I'm not sure why you need the fudge factor -- maybe some padding in the label? I tested it with different length strings and different font sizes, and it always worked correctly.

- (CSPostCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    CSPostCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SelfPostCell" forIndexPath:indexPath];
    cell.postTitle.text = indexPath.row == 0 ? @"Short title" : @"Long long long title. Holy crap this is one long title. When does it end? Oh right now.";
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    CSPostCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SelfPostCell"];
    cell.postTitle.text = indexPath.row == 0 ? @"Short title" : @"Long long long title. Holy crap this is one long title. When does it end? Oh right now.";
    cell.postTitle.preferredMaxLayoutWidth = tableView.bounds.size.width - 40;
    CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
    return height + 2;
}
rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • I'm not sure why all the different updateConstraints are there, but they [seem to be necessary](http://stackoverflow.com/questions/20305654/what-is-the-difference-between-all-these-auto-layout-update-methods-are-all-nec) see also the GitHub example. And what is a fudge factor, is that the 2 points you added? And interesting, thanks for the solution. Very odd it doesn't work "out of the box" though without needing a magic number tweak. – Doug Smith Dec 01 '13 at 16:14
  • @DougSmith, are they necessary when you try it? It didn't make any difference when I removed them all. And yes, the +2 is the fudge factor I added. – rdelmar Dec 01 '13 at 16:23
  • 1
    by adding +2 you are counting in a height of cell separator. Actually, +1 is enough. If you don't show cell separators (UITableViewCellSeparatorStyleNone), then just use height value without modification. – andrejs Jul 04 '14 at 15:21
  • `return height +1` is for the separator. A more flexible method is `CGFloat separator = ((UITableViewCellSeparatorStyleNone != self.tableView.separatorStyle) ? 1 : 0); return height + separator; }` – SwiftArchitect Jun 16 '15 at 00:35