Search code examples
swiftconstraints

How can I set priority on constraints in Swift?


I've been struggling to make priority on constraints work programmatically in Swift.

My goal is to have the meetingFormView no more than 300 wide. Using IB I would give the width constraint a lower priority and give a higher priority to the "lessThanOrEqualToConstant". But I can't get it to work.

I've tried this:

meetingFormView.translatesAutoresizingMaskIntoConstraints = false

let constraintWidth = NSLayoutConstraint(
        item: meetingFormView,
        attribute: NSLayoutAttribute.width,
        relatedBy: NSLayoutRelation.equal,
        toItem: startView,
        attribute: NSLayoutAttribute.width,
        multiplier: 1,
        constant: 0)
constraintWidth.priority = .defaultHigh

NSLayoutConstraint.activate([
    meetingFormView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20),
    meetingFormView.heightAnchor.constraint(equalToConstant: 170),
    meetingFormView.widthAnchor.constraint(lessThanOrEqualToConstant: 300),
    meetingFormView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
    constraintWidth
])

Solution

  • It actually seems to take three lines of code to set up a prioritized "anchor-based" constraint in code:

    let widthConstraint = meetingFormView.widthAnchor.constraint(equalToConstant: 170)
    widthConstraint.priority = UILayoutPriority(rawValue: 500)
    widthConstraint.isActive = true
    

    It seems like if I try to set isActive with the let declare Xcode (maybe Swift?) doesn't recognize that the type is NSLayoutConstraint. And using UILayoutPriority(rawValue:) seems to be the best (only?) way to set priorities.

    While this answer doesn't conform exactly with what you are doing, I believe it will work with IB. Just replace the let with creating an IBOutlet and there should be no need for the isActive line.

    Obviously, to change the priority later in code you just need:

    widthConstraint.priority = UILayoutPriority(rawValue: 750)