简体   繁体   中英

How do I add an identifier to auto layout anchor constraints?

I want to add identifiers to all my constraints so I can debug an issue. The problem is that I don't create all my constraints directly if I use anchors. I can create a constraint:

 let constraint = NSLayoutConstraint(item: view, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 60.0)

but then I'd have to add it to the view, not the heightAnchor (there is no .addConstraint() method associated with UIStackViews)

So how do I add identifiers to the constraints auto-generated by these lines of code:

    view.heightAnchor.constraint(equalToConstant: 60.0).isActive = true
    view.widthAnchor.constraint(equalToConstant: 60.0).isActive = true

anchors are supposed to make programming auto layout easier, but surely not at the expense of being unable to debug properly? If I can't add identifiers, how do I debug my “unsatisfiable” constraints exception?

Your code returns you constraint, so you can add identifier to it like this

let myConstraint = view.heightAnchor.constraint(equalToConstant: 60.0)
myConstraint.identifier = "myIdentifier"
myConstraint.isActive = true

Look at the answer I gave in this question . It will give you an answer to your question.

(there is no .addConstraint() method

Yes, there is:

NSLayoutConstraint.activate([constraintvariable])

Edit:

Alright, if I understand your question correctly:

let vHeightConstraint = self.view.heightAnchor.constraint(equalToConstant: 60.0);
vHeightConstraint.isActive = true
vHeightConstraint.identifier = "Your identifier"

This way you'll have a variable for you constraint and that will be available under debugging to see it's value.

I use arrays and activate/deactivate them:

var p = [NSLayoutConstraint]() // portrait constraints
var l = [NSLayoutConstraint]() // landscape constraints

// (an example of this) pin segmentedView to top

p.append(segmentedControl.topAnchor.constraint(equalTo: imageLayout.topAnchor))
p.append(segmentedControl.widthAnchor.constraint(equalToConstant: 300))
p.append(segmentedControl.centerXAnchor.constraint(equalTo: imageLayout.centerXAnchor))
l.append(segmentedControl.topAnchor.constraint(equalTo: imageLayout.topAnchor))
l.append(segmentedControl.widthAnchor.constraint(equalToConstant: 300))
l.append(segmentedControl.centerXAnchor.constraint(equalTo: imageLayout.centerXAnchor))

public func setOrientation(_ p:[NSLayoutConstraint], _ l:[NSLayoutConstraint]) {
    NSLayoutConstraint.deactivate(l)
    NSLayoutConstraint.deactivate(p)
    if self.bounds.width > self.bounds.height {
        NSLayoutConstraint.activate(l)
    } else {
        NSLayoutConstraint.activate(p)
    }
}

You get the idea.... move your constraints into an array and activate/deactivate as needed.

I have a different approach using Swift 4.2. I hope that may be useful.

extension UIView{

    func getConstraint(forAttribute attribute:NSLayoutConstraint.Attribute)->NSLayoutConstraint?{

        for aConstraint in constraints{

            if aConstraint.firstAttribute == attribute{

                return aConstraint

            }

        }

        return nil

    }

}

so you can do;

@IBOutlet weak var confirmButton: MainButton!{
    didSet{
        confirmButton.getConstraint(forAttribute: .height)!.identifier = aID
        confirmButton.isEnabled = false
    }
}

or

myOtherButton.getConstraint(forAttribute: .height)?.identifier = "newIdentifier"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM