SolvedSnapKit crash: Updated constraint could not find existing matching constraint to update

New Issue Checklist

Issue Info

Info Value
Platform ios
Platform Version 10
SnapKit Version 0.40.0 (2e4cebf)
Integration Method carthage

Issue Description

I've just migrated my app to Swift3 and hence also switched to version 0.40 unfortunately it now crashes on startup. I am seeing

NSHashTable {
[0] <SnapKit.LayoutConstraint:0x6000000bf3e0@ReloadView.swift#47 UILabel:0x7faa7bc38770.top == Foo.ReloadView:0x7faa7bc35340.top + 20.0>
}
 NSHashTable {
[0] <SnapKit.LayoutConstraint:0x6000000bf3e0@ReloadView.swift#47 UILabel:0x7faa7bc38770.top == Foo.ReloadView:0x7faa7bc35340.top + 20.0>
}

fatal error: Updated constraint could not find existing matching constraint to update: <SnapKit.LayoutConstraint:0x6000000bf440@ReloadView.swift#48 UILabel:0x7faa7bc38770.left == Foo.ReloadView:0x7faa7bc35340.left + 20.0>: file /project/Carthage/Checkouts/SnapKit/Source/Constraint.swift, line 233

A stripped down version of the view controller and view looks like this:

class ReloadView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        configure()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        configure()
    }

    convenience init() {
        self.init(frame: CGRect.zero)
    }

    func configure() {

        let label = UILabel()
        let button = UIButton(type: UIButtonType.roundedRect)

        addSubview(label)
        addSubview(button)

        let padding = 20

        label.snp.updateConstraints { make in
            make.top.equalTo(padding)
            make.left.equalTo(self).offset(padding)
            make.right.equalTo(self).offset(-padding)
            make.width.equalTo(300)
        }

        button.snp.updateConstraints { make in
            make.top.equalTo(label.snp.bottom).offset(padding)
            make.left.equalTo(padding)
            make.width.equalTo(self).offset(-2*padding)
            make.bottom.equalTo(0).offset(-padding)
        }
    }
}
class FooViewController: UIViewController {

    private var reloadView: ReloadView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let reloadView = ReloadView()
        self.reloadView = reloadView

        view.addSubview(reloadView)

        reloadView.snp.updateConstraints { make in
            // make.center.equalToSuperview()
            make.edges.equalTo(view.snp.edges)
        }

    }
}
17 Answers

✔️Accepted Answer

@tcurdt you should:

  • Use makeConstraints where code executes exactly once OR you need to add more constraints to existing ones
  • Use remakeConstraints where you have new attribute combinations (e.g. changing left = right to left = left ) and want to throw away all existing constraints and make new ones
  • Use updateConstraints where you have identical attribute combinations and just want to update the constant value (e.g. offset(10) to offset(20)

updateConstraints and remakeConstraints both act like makeConstraints if the from view has no existing constraints created from SnapKit.

More Issues: