I'm trying to implement self sizing tableview cell. I set autolayout height inside the cell but it show autolayout error.
I set translatesAutoresizingMaskIntoConstraints = false and setting UITableView.autoDimension.
It show autolayout error as below.
[LayoutConstraints] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x6000024ce9e0 DisposeSecond.MyCell:0x7f9ba7104aa0'cell'.height == 100 (active)>",
"<NSLayoutConstraint:0x6000024ce800 'UIView-Encapsulated-Layout-Height' DisposeSecond.MyCell:0x7f9ba7104aa0'cell'.height == 100.333 (active)>"
)
My implementation is quite simple.
import UIKit
class MyCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
translatesAutoresizingMaskIntoConstraints = false
self.heightAnchor.constraint(equalToConstant: 100).isActive = true
// Set debug colors to visualize heigh
layer.borderWidth = 2
layer.borderColor = UIColor.blue.cgColor
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
class MyTableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(MyCell.self, forCellReuseIdentifier: "cell")
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 30
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyCell
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// I know it is set automatically but just indeed
return UITableView.automaticDimension
}
}
First issue: as a general rule, you should never modify the cell view itself with things like:
translatesAutoresizingMaskIntoConstraints = false
self.heightAnchor.constraint(equalToConstant: 100).isActive = true
instead, modify the cell contents:
contentView.heightAnchor.constraint(equalToConstant: 100.0).isActive = true
Next, when using auto-sizing cells and table views (or collection views), auto-layout often encounters conflicts as it makes multiple passes. This is due to things like separators, object encapsulated dimensions, etc.
You can avoid that by using a priority
of 999
on the constraints instead of the default 1000
:
// create heightAnchor for contentView
let c = contentView.heightAnchor.constraint(equalToConstant: 100.0)
// set priority to 999 to avoid auto-layout conflicts with auto-sizing cells
c.priority = UILayoutPriority(rawValue: 999)
// activate it
c.isActive = true
Third, implementing heightForRowAt
is almost never needed when using auto-layout and auto-sizing cells. Unless you know specifically why you need to implement it, don't.
Here is your cell class, modified with the above notes:
class MyCell: UITableViewCell {
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
// never modify self in this way
//translatesAutoresizingMaskIntoConstraints = false
//self.heightAnchor.constraint(equalToConstant: 100).isActive = true
// create heightAnchor for contentView
let c = contentView.heightAnchor.constraint(equalToConstant: 100.0)
// set priority to 999 to avoid auto-layout conflicts with auto-sizing cells
c.priority = UILayoutPriority(rawValue: 999)
// activate it
c.isActive = true
// Set debug colors to visualize heigh
layer.borderWidth = 2
layer.borderColor = UIColor.blue.cgColor
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}