There are two buttons named buttonA
and buttonB
in a same view, I have set their constraints in storyboard. How can I exchange their constraints programmatically?
I was looking for an answer of this and I ended up doing it in the following way:
(Code examples are in Swift 3
)
Let's say you have a UIView called containerView
which contains two UIViews: subviewA
and subviewB
.
The constraints for the subviews are actually defined within containerView
(as per the rule of the "closest common ancestor").
This solution also assumes that the constraints have as a 'First Item' subViewA
or subViewB
and as a 'Second Item' containerView
. If your setup is different you might need to modify the code accordingly.
So we have a function that swaps constraints:
private func swapFirstItemsOfConstraintsDefinedInThisView(_ superview: UIView, betweenItem item1: AnyObject, andItem item2: AnyObject)
{
var constraintsToRemove: [NSLayoutConstraint] = []
var constraintsNew_item1: [NSLayoutConstraint] = []
var constraintsNew_item2: [NSLayoutConstraint] = []
for constraint in superview.constraints
{
if (constraint.firstItem === item1)
{
constraintsToRemove.append(constraint)
constraintsNew_item1.append(NSLayoutConstraint(item: item2, attribute: constraint.firstAttribute, relatedBy: constraint.relation, toItem: constraint.secondItem, attribute: constraint.secondAttribute, multiplier: constraint.multiplier, constant: constraint.constant))
}
else if (constraint.firstItem === item2)
{
constraintsToRemove.append(constraint)
constraintsNew_item2.append(NSLayoutConstraint(item: item1, attribute: constraint.firstAttribute, relatedBy: constraint.relation, toItem: constraint.secondItem, attribute: constraint.secondAttribute, multiplier: constraint.multiplier, constant: constraint.constant))
}
}
superview.removeConstraints(constraintsToRemove);
superview.addConstraints(constraintsNew_item1);
superview.addConstraints(constraintsNew_item2);
}
So then you can call the following (in your ViewController
somewhere):
self.swapFirstItemsOfConstraintsDefinedInThisView(self.containerView, betweenItem: subviewA, andItem: subviewB)
self.containerView.layoutIfNeeded()
Note that the effects of the swap won't be shown unless you call the layoutIfNeeded()
. Depending on your needs, you might want to add this call as the last line of the body of the swap function.
By the way if you call layoutIfNeeded()
in an UIAnimation
context (in the animations
closure/block) it would animate the transition.
Note that there a lot of potential improvements of this code, it's just an example of the basic approach. For instance we could have an extension on NSLayoutConstraint
to allow init
ting it by copying another NSLayoutConstraint
and changing only the 'First item' property (so that we avoid the long repeated lines of code above). Also the swap function itself could be defined in an extension of UIView
. And performance-wise there are potential issues with the above implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With