Created
December 3, 2014 17:28
-
-
Save smileyborg/0a2082a4d26fcc7fde4d to your computer and use it in GitHub Desktop.
mluisbrown/TableViewCellWithAutoLayout
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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]; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The main fix is here: https://gist.github.com/smileyborg/0a2082a4d26fcc7fde4d#file-rjtableviewcontroller-m-L43
You'll also want to uncomment this line to prevent irrelevant constraint exceptions: https://gist.github.com/smileyborg/0a2082a4d26fcc7fde4d#file-rjtableviewcell-m-L9