UITableViewHeaderFooterContentView's width should equal 0

No it shouldn’t!

You probably have seen this error in your Xcode console if you use Auto Layout for UITableViewCell or UITableViewHeaderFooterContentView. Then you examine the code and found nothing wrong. Even the UI looks correct.

(
    "<NSLayoutConstraint:0x600002b60e10 UIStackView:0x7fa820c65b60.leading == UILayoutGuide:0x6000031bf2c0'UIViewLayoutMarginsGuide'.leading   (active)>",
    "<NSLayoutConstraint:0x600002b60e60 UIStackView:0x7fa820c65b60.trailing == UILayoutGuide:0x6000031bf2c0'UIViewLayoutMarginsGuide'.trailing   (active)>",
    "<NSLayoutConstraint:0x600002b60f00 H:|-(0)-[UIView:0x7fa820c65cf0]   (active, names: '|':_UITableViewHeaderFooterContentView:0x7fa820c63e50 )>",
    "<NSLayoutConstraint:0x600002b60f50 UIView:0x7fa820c65cf0.trailing == _UITableViewHeaderFooterContentView:0x7fa820c63e50.trailing   (active)>",
    // Notice this one
    "<NSLayoutConstraint:0x600002b61720 'UIView-Encapsulated-Layout-Width' _UITableViewHeaderFooterContentView:0x7fa820c63e50.width == 0   (active)>",
    "<NSLayoutConstraint:0x600002b60d20 'UIView-leftMargin-guide-constraint' H:|-(33)-[UILayoutGuide:0x6000031bf2c0'UIViewLayoutMarginsGuide'](LTR)   (active, names: '|':UIView:0x7fa820c65cf0 )>",
    "<NSLayoutConstraint:0x600002b60dc0 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x6000031bf2c0'UIViewLayoutMarginsGuide']-(33)-|(LTR)   (active, names: '|':UIView:0x7fa820c65cf0 )>"
)

This post that ranks high on Google explains this problem well. However, it suggests us to set half of UILayoutConstraints’ priority to 999.

Well, I wouldn’t go that far to mess up with all constraints priority.

A better approach is only setting 999 priority for those constraint that temporarily breaks Auto Layout when UITableView is busy doing layout. The take away is, if you set layoutMargins to a UITableViewCell, you will probably want to set this view’s priority to 999.

So, in your UITableView cell:

override init(reuseIdentifier: String?) {
    super.init(reuseIdentifier: reuseIdentifier)

    let containerView = UIView()

    // The bug: Setting a margins to non-zeor will conflicts with UITableView's auto constraint where the cell's width should be equal to 0
    containerView.layoutMargins = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15)

    // Set priority = 999 because UITableView will set Width=0 temporarily that makes the console ugly
    hStack.pinToMargins(of: containerView, edges: [.leading, .trailing], priority: .required - 1)

    contentView.addSubview(containerView)
    containerView.pinEdges(to: contentView)
}

If you use my layout utility class, it will be blazingly easy to setup constraints with desired priority.

Posted 2020-06-13

More writing at jakehao.com

Discussions on Twitter