Skip to content

Instantly share code, notes, and snippets.

@smileyborg
Created December 3, 2014 17:28
Show Gist options
  • Save smileyborg/0a2082a4d26fcc7fde4d to your computer and use it in GitHub Desktop.
Save smileyborg/0a2082a4d26fcc7fde4d to your computer and use it in GitHub Desktop.
mluisbrown/TableViewCellWithAutoLayout
/* Note that I have uncommented Line 9 to prevent constraint exceptions before the cells actually layout at their correct size. */
- (void)updateConstraints
{
if (!self.didSetupConstraints) {
// Note: if the constraints you add below require a larger cell size than the current size (which is likely to be the default size {320, 44}), you'll get an exception.
// As a fix, you can temporarily increase the size of the cell's contentView so that this does not occur using code similar to the line below.
// See here for further discussion: https://github.com/Alex311/TableCellWithAutoLayout/commit/bde387b27e33605eeac3465475d2f2ff9775f163#commitcomment-4633188
self.contentView.bounds = CGRectMake(0.0f, 0.0f, 99999.0f, 99999.0f);
// the image view is pinned to the edges of the content view with a 15px inset
// this should be enough to force the height of the content view
[self.mainImage autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(15, 15, 15, 15)];
// if you set a fixed height constraint, there is no problem, the cell's
// contentView height is pushed out to fit this constraint
// [self.mainImage autoSetDimension:ALDimensionHeight toSize:100];
// make the height of the image view equal to 0.5 the width of the contentView. This
// doesn't result in 'forcing' the cell's contentView height
[self.mainImage autoMatchDimension:ALDimensionHeight toDimension:ALDimensionWidth ofView:self.contentView withMultiplier:0.5 relation:NSLayoutRelationGreaterThanOrEqual];
// [UIView autoSetPriority:UILayoutPriorityRequired forConstraints:^{
// [self.titleLabel autoSetContentCompressionResistancePriorityForAxis:ALAxisVertical];
// }];
// [self.titleLabel autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:kLabelVerticalInsets];
// [self.titleLabel autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:kLabelHorizontalInsets];
// [self.titleLabel autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:kLabelHorizontalInsets];
//
// // This is the constraint that connects the title and body labels. It is a "greater than or equal" inequality so that if the row height is
// // slightly larger than what is actually required to fit the cell's subviews, the extra space will go here. (This is the case on iOS 7
// // where the cell separator is only 0.5 points tall, but in the tableView:heightForRowAtIndexPath: method of the view controller, we add
// // a full 1.0 point in extra height to account for it, which results in 0.5 points extra space in the cell.)
// // See https://github.com/smileyborg/TableViewCellWithAutoLayout/issues/3 for more info.
// [self.bodyLabel autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.titleLabel withOffset:kLabelVerticalInsets relation:NSLayoutRelationGreaterThanOrEqual];
//
// [UIView autoSetPriority:UILayoutPriorityRequired forConstraints:^{
// [self.bodyLabel autoSetContentCompressionResistancePriorityForAxis:ALAxisVertical];
// }];
// [self.bodyLabel autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:kLabelHorizontalInsets];
// [self.bodyLabel autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:kLabelHorizontalInsets];
// [self.bodyLabel autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:kLabelVerticalInsets];
self.didSetupConstraints = YES;
}
[super updateConstraints];
}
/* Note the addition of Line 43. */
- (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.
// Adding this constraint allows the sizing calculations to factor in the correct table view width,
// which is necessary because of the constraint matching the height relative to the width of the cell
[cell.contentView autoSetDimension:ALDimensionWidth toSize:CGRectGetWidth(tableView.bounds)];
// 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;
}
@smileyborg
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment