Trying to find a solution to update multiple constraints for multiple UI elements on an event. I have seen some examples of deactivating, making a change, then reactivating constraints, this method seems impractical for the 24 anchors I am working with.
One of my sets of changes:
ticketContainer.translatesAutoresizingMaskIntoConstraints = false
ticketContainer.topAnchor.constraintEqualToAnchor(self.topAnchor).active = true
ticketContainer.leftAnchor.constraintEqualToAnchor(self.rightAnchor, constant: 20).active = true
ticketContainer.widthAnchor.constraintEqualToConstant(200.0).active = true
ticketContainer.leftAnchor.constraintEqualToAnchor(self.leftAnchor, constant: 20).active = true
ticketContainer.widthAnchor.constraintEqualToConstant(100.0).active = true
Have you tried saving the relevant constraints you created using the layout anchors to properties, and then just changing the constant? E.g.
var ticketTop : NSLayoutConstraint?
func setup() {
ticketTop = ticketContainer.topAnchor.constraintEqualToAnchor(self.topAnchor, constant:100)
ticketTop.active = true
}
func update() {
ticketTop?.constant = 25
}
Depending on your taste for writing extensions, here is a possibly more elegant approach that doesn't use properties, but instead creates extension methods on NSLayoutAnchor
and UIView
to aid in more succinct usage.
First you would write an extension on NSLayoutAnchor
like this:
extension NSLayoutAnchor {
func constraintEqualToAnchor(anchor: NSLayoutAnchor!, constant:CGFloat, identifier:String) -> NSLayoutConstraint! {
let constraint = self.constraintEqualToAnchor(anchor, constant:constant)
constraint.identifier = identifier
return constraint
}
}
This extension allows you to set an identifier on the constraint in the same method call that creates it from an anchor. Note that Apple documentation implies that XAxis anchors (left, right, leading, etc.) won't let you create a constraint with YAxis anchors (top, bottom, etc.), but I don't observe this to actually be true. If you did want that type of compiler checking, you would need to write separate extensions for NSLayoutXAxisAnchor
, NSLayoutYAxisAnchor
, and NSLayoutDimension
(for width and height constraints) that enforce the same-axis anchor type requirement.
Next you would write an extension on UIView
to get a constraint by identifier:
extension UIView {
func constraint(withIdentifier:String) -> NSLayoutConstraint? {
return self.constraints.filter{ $0.identifier == withIdentifier }.first
}
}
With these extensions in place, your code becomes:
func setup() {
ticketContainer.topAnchor.constraintEqualToAnchor(anchor: self.topAnchor, constant:100, identifier:"ticketTop").active = true
}
func update() {
self.constraint(withIdentifier:"ticketTop")?.constant = 25
}
Note that using constants or an enum instead of magic string names for the identifiers would be an improvement over the above, but I'm keeping this answer brief and focused.