Skip to content

Instantly share code, notes, and snippets.

@jonathan-beebe
Created January 8, 2015 20:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonathan-beebe/e83d7aa67dacdd4e2b70 to your computer and use it in GitHub Desktop.
Save jonathan-beebe/e83d7aa67dacdd4e2b70 to your computer and use it in GitHub Desktop.
Using UITableViewCell with dynamic height & autolayout
// https://github.com/smileyborg/TableViewCellWithAutoLayout/blob/master/TableViewCellWithAutoLayout/TableViewController/RJTableViewController.m
// http://stackoverflow.com/a/18746930/123781
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// This project has only one cell identifier, but if you are have more than one, this is the time
// to figure out which reuse identifier should be used for the cell at this index path.
NSString *reuseIdentifier = CellIdentifier;
// Use the dictionary of offscreen cells to get a cell for the reuse identifier, creating a cell and storing
// it in the dictionary if one hasn't already been added for the reuse identifier.
// WARNING: Don't call the table view's dequeueReusableCellWithIdentifier: method here because this will result
// in a memory leak as the cell is created but never returned from the tableView:cellForRowAtIndexPath: method!
RJTableViewCell *cell = [self.offscreenCells objectForKey:reuseIdentifier];
if (!cell) {
cell = [[RJTableViewCell alloc] init];
[self.offscreenCells setObject:cell forKey:reuseIdentifier];
}
// Configure the cell for this indexPath
[cell updateFonts];
NSDictionary *dataSourceItem = [self.model.dataSource objectAtIndex:indexPath.row];
cell.titleLabel.text = [dataSourceItem valueForKey:@"title"];
cell.bodyLabel.text = [dataSourceItem valueForKey:@"body"];
// Make sure the constraints have been added to this cell, since it may have just been created from scratch
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
// The cell's width must be set to the same size it will end up at once it is in the table view.
// This is important so that we'll get the correct height for different table view widths, since our cell's
// height depends on its width due to the multi-line UILabel word wrapping. Don't need to do this above in
// -[tableView:cellForRowAtIndexPath:] because it happens automatically when the cell is used in the table view.
cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));
// NOTE: if you are displaying a section index (e.g. alphabet along the right side of the table view), or
// if you are using a grouped table view style where cells have insets to the edges of the table view,
// you'll need to adjust the cell.bounds.size.width to be smaller than the full width of the table view we just
// set it to above. See http://stackoverflow.com/questions/3647242 for discussion on the section index width.
// Do the layout pass on the cell, which will calculate the frames for all the views based on the constraints
// (Note that the preferredMaxLayoutWidth is set on multi-line UILabels inside the -[layoutSubviews] method
// in the UITableViewCell subclass
[cell setNeedsLayout];
[cell layoutIfNeeded];
// Get the actual height required for the cell
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;
// Add an extra point to the height to account for the cell separator, which is added between the bottom
// of the cell's contentView and the bottom of the table view cell.
height += 1;
return height;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment