Snapkit LayoutConstraints Unable to simultaneously satisfy constraints

680 Views Asked by At

I have simple UITableView and custom UITablViewCell in my project, which created programmatically and use SnapKit for auto layout its. When I run app, everything work fine and get some LayoutConstraints error in debug console.

enter image description here

UITableViewCell

import UIKit
import SnapKit
class TestTableViewCell: UITableViewCell {
    
    ...
    private lazy var containerView: UIView = {
        let view = UIView()
        return view
    }()
    
    private lazy var centerStackView: UIStackView = {
        let stackView = UIStackView(arrangedSubviews: [titleLabel, disclosureImageView])
        stackView.axis = .horizontal
        stackView.distribution = .fill
        stackView.spacing = 5.0
        return stackView
    }()
    
    private lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
        return label
    }()
    
    private lazy var disclosureImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.contentMode = .scaleAspectFit
        imageView.image = UIImage(named: "disclosure")
        return imageView
    }()
    
   ..
    
    private func setupUI() {
        selectionStyle = .none
        backgroundColor = .background
        contentView.addSubview(containerView)
        containerView.backgroundColor = .white
        containerView.layer.cornerRadius = 12
        containerView.clipsToBounds = true
        containerView.addSubview(centerStackView)
        setNeedsUpdateConstraints()
    }
    
    // MARK: - Update Constraints
    override func updateConstraints() {
        containerView.snp.updateConstraints { make in
            make.top.bottom.equalToSuperview().inset(8)
            make.leading.trailing.equalToSuperview().inset(16)
            make.height.equalTo(100)
        }
        
        centerStackView.snp.updateConstraints { make in
            make.center.equalToSuperview()
        }
        
        super.updateConstraints()
    }
}

How I can fix this constraint error ?

1

There are 1 best solutions below

2
Sweeper On

There are actually two conflicts for each table view cell. You can copy-paste the sets of constraints are in conflict into https://www.wtfautolayout.com and see exactly why they are conflicting. As a result, we get this and this.

We can see that the first conflict is caused by your container view having a height constraint, but the table view itself also adds a height constraint to the cell to enforce its cells' sizes,

"<NSLayoutConstraint:0x7b1400031920 'UIView-Encapsulated-Layout-Height' UITableViewCellContentView:0x7b4c00003640.height == 116.5   (active)>"

For some reason, the constant here is 116.5, not 116 as you would expect from the 100 points of height of the container view + the 16 points of inset.

You can either change it to

make.height.greaterThanOrEqualTo(100)

Or remove the height constraint completely:

// make.height.equalTo(100)

and use the delegate method heightForRowAt to control the cell height instead:

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    116
}

As for the second conflict, it is caused by a constraint constraining the stack view's width to 0, being in conflict with the fact that there must be some spacing between the image and label.

"<NSLayoutConstraint:0x7b1400031b50 'UIView-Encapsulated-Layout-Width' UIStackView:0x7b4c000039c0.width == 0   (active)>"

If you move the following code from updateConstraints into setupUI, the conflict is resolved:

containerView.snp.updateConstraints { make in
    make.top.bottom.equalToSuperview().inset(8)
    make.leading.trailing.equalToSuperview().inset(16)
    make.height.greaterThanOrEqualTo(100)
}

centerStackView.snp.updateConstraints { make in
    make.center.equalToSuperview()
}