UITableView dynamic cell heights only correct afte

2019-01-10 04:39发布

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.

Sample project: Top of table view from sample project on first load. Sample project: Same cells after scrolling down and back up.

22条回答
Luminary・发光体
2楼-- · 2019-01-10 04:50

I have a similar problem, at the first load, the row height was not calculated but after some scrolling or go to another screen and i come back to this screen rows are calculated. At the first load my items are loaded from the internet and at the second load my items are loaded first from Core Data and reloaded from internet and i noticed that rows height are calculated at the reload from internet. So i noticed that when tableView.reloadData() is called during segue animation (same problem with push and present segue), row height was not calculated. So i hidden the tableview at the view initialization and put an activity loader to prevent an ugly effect to the user and i call tableView.reloadData after 300ms and now the problem is solved. I think it's a UIKit bug but this workaround make the trick.

I put theses lines (Swift 3.0) in my item load completion handler

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300), execute: {
        self.tableView.isHidden = false
        self.loader.stopAnimating()
        self.tableView.reloadData()
    })

This explain why for some people, put a reloadData in layoutSubviews solve the issue

查看更多
神经病院院长
3楼-- · 2019-01-10 04:50

Setting preferredMaxLayoutWidth helps in my case. I added

cell.detailLabel.preferredMaxLayoutWidth = cell.frame.width

in my code.

Also refer to Single line text takes two lines in UILabel and http://openradar.appspot.com/17799811.

查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-01-10 04:51

I have the issue with resizing label so I nee just to do
chatTextLabel.text = chatMessage.message chatTextLabel?.updateConstraints() after setting up the text

// full code

func setContent() {
    chatTextLabel.text = chatMessage.message
    chatTextLabel?.updateConstraints()

    let labelTextWidth = (chatTextLabel?.intrinsicContentSize().width) ?? 0
    let labelTextHeight = chatTextLabel?.intrinsicContentSize().height

    guard labelTextWidth < originWidth && labelTextHeight <= singleLineRowheight else {
      trailingConstraint?.constant = trailingConstant
      return
    }
    trailingConstraint?.constant = trailingConstant + (originWidth - labelTextWidth)

  }
查看更多
Evening l夕情丶
5楼-- · 2019-01-10 04:53

In my case the last line of the UILabel was truncated when the cell was displayed for the first time. It happened pretty randomly and the only way to size it correctly was to scroll the cell out of the view and to bring it back. I tried all the possible solutions displayed so far (layoutIfNeeded..reloadData) but nothing worked for me. The trick was to set "Autoshrink" to Minimuum Font Scale (0.5 for me). Give it a try

查看更多
祖国的老花朵
6楼-- · 2019-01-10 04:54

calling cell.layoutIfNeeded() inside cellForRowAt worked for me on ios 10 and ios 11, but not on ios 9.

to get this work on ios 9 also, I call cell.layoutSubviews() and it did the trick.

查看更多
手持菜刀,她持情操
7楼-- · 2019-01-10 04:54

In my case, the issue with the cell height takes place after the initial table view is loaded, and a user action takes place (tapping on a button in a cell that has an effect of changing the cell height). I have been unable to get the cell to change its height unless I do:

[self.tableView reloadData];

I did try

[cell layoutIfNeeded];

but that didn't work.

查看更多
登录 后发表回答