A self-sizing cell renders at the wrong height on first layout
This cell should size itself to its label, but every row renders at the estimated height instead of the real one. The table sets estimatedRowHeight = 44 and rowHeight = .automaticDimension.
Find and fix the bug in the cell's constraints.
final class ProductCell: UITableViewCell {
let title = UILabel()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
title.numberOfLines = 0
title.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(title)
NSLayoutConstraint.activate([
title.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12),
title.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
title.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
])
}
required init?(coder: NSCoder) { fatalError() }
}
Find and fix the bug.
title is pinned top, leading, and trailing but never to contentView.bottomAnchor, so the vertical chain never reaches the bottom and the cell height is ambiguous, staying at the estimate. Add the missing bottom constraint so the height flows from content.
- ✗Leaving a gap in the top-to-bottom constraint chain of the contentView
- ✗Treating the estimate as the final height rather than a placeholder
- ✗Blaming reload timing instead of the ambiguous vertical constraints
- →Why must the chain reach
contentView.bottomAnchorspecifically, not the cell's? - →How would a multiline label's
numberOfLines = 0interact with this chain?
The cell can't be measured because its vertical constraints stop at the label's top: nothing ties title's bottom to contentView.bottomAnchor, so the content view has no way to derive its own height. Auto Layout marks the height ambiguous and the table keeps the 44-pt estimate. The fix is to close the top-to-bottom chain:
NSLayoutConstraint.activate([
title.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 12),
title.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16),
title.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16),
// the missing rung — now content height flows to the cell:
title.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -12),
])
With estimatedRowHeight > 0 and rowHeight = .automaticDimension already set, the completed chain lets a multiline label (numberOfLines = 0) grow and push the cell to its true height. The estimate only seeds the initial scroll metrics; the constraint chain produces the final size.