I have a UITableView
with a custom UITableViewCell
defined in a storyboard using auto layout. The cell has several multiline UILabels
.
The UITableView
appears to properly calculate cell heights, but for the first few cells that height isn't properly divided between the labels.
After scrolling a bit, everything works as expected (even the cells that were initially incorrect).
- (void)viewDidLoad {
[super viewDidLoad]
// ...
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
// ...
// Set label.text for variable length string.
return cell;
}
Is there anything that I might be missing, that is causing auto layout not to be able to do its job the first few times?
I've created a sample project which demonstrates this behaviour.
Just make sure you're not setting the label text in 'willdisplaycell' delegate method of table view. Set the label text in 'cellForRowAtindexPath' delegate method for dynamic height calculation.
You're Welcome :)
The problem is that the initial cells load before we have a valid row height. The workaround is to force a table reload when the view appears.
I have tried most of the answers to this question and could not get any of them to work. The only functional solution I found was to add the following to my
UITableViewController
subclass:The
UIView.performWithoutAnimation
call is required, otherwise you will see the normal table view animation as the view controller loads.In Swift 3. I had to call self.layoutIfNeeded() each time I update the text of the reusable cell.
I don't know this is clearly documented or not, but adding
[cell layoutIfNeeded]
before returning cell solves your problem.I had same experience in one of my projects.
Why it happens?
Cell designed in Storyboard with some width for some device. For example 400px. For example your label have same width. When it loads from storyboard it have width 400px.
Here is a problem:
tableView:heightForRowAtIndexPath:
called before cell layout it's subviews.So it calculated height for label and cell with width 400px. But you run on device with screen, for example, 320px. And this automatically calculated height is incorrect. Just because cell's
layoutSubviews
happens only aftertableView:heightForRowAtIndexPath:
Even if you setpreferredMaxLayoutWidth
for your label manually inlayoutSubviews
it not helps.My solution:
1) Subclass
UITableView
and overridedequeueReusableCellWithIdentifier:forIndexPath:
. Set cell width equal to table width and force cell's layout.2) Subclass
UITableViewCell
. SetpreferredMaxLayoutWidth
manually for your labels inlayoutSubviews
. Also you need manually layoutcontentView
, because it doesn't layout automatically after cell frame change (I don't know why, but it is)