I have a view which has dynamic height and I am trying to change this view height priority in run time.
Here is my part of code;
if (index == 0) {
According to NSLayoutConstraints class
inside UIKit Module
If a constraint's priority level is less than UILayoutPriorityRequired, then it is optional. Higher priority constraints are met before lower priority constraints. Constraint satisfaction is not all or nothing. If a constraint 'a == b' is optional, that means we will attempt to minimize 'abs(a-b)'. This property may only be modified as part of initial set up or when optional. After a constraint has been added to a view, an exception will be thrown if the priority is changed from/to NSLayoutPriorityRequired.
Example:- UIButton
constraints with various priorities -
func setConstraints() {
buttonMessage.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: buttonMessage, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: -10).isActive = true
let leading = NSLayoutConstraint(item: buttonMessage, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 10)
leading.isActive = true
let widthConstraint = NSLayoutConstraint(item: buttonMessage, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100)
let heightConstraint = NSLayoutConstraint(item: buttonMessage, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 50)
let trailingToSuperView = NSLayoutConstraint(item: buttonMessage, attribute: .trailing, relatedBy: .equal, toItem: view, attribute: .trailing, multiplier: 1, constant: 0)
trailingToSuperView.priority = 999
trailingToSuperView.isActive = true
//leading.isActive = false//uncomment & check it will align to right of the View
buttonMessage.addConstraints([widthConstraint,heightConstraint])
}
I want to make a small addition to Cyrille's answer.
If you are creating constraint in code, make sure to set its priority before making it active. For instance:
surveyViewHeightConstraint = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.superview
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0];
surveyViewHeightConstraint.active = YES;
surveyViewHeightConstraint.priority = 999;
This would result in run-time exception.
Mutating a priority from required to not on an installed constraint (or vice-versa) is not supported.
Correct order is:
surveyViewHeightConstraint.priority = 999;
surveyViewHeightConstraint.active = YES;
For Swift version 4+
constraintName.priority = UILayoutPriority(rawValue: 999)
Swift version:
myContraint.priority = UILayoutPriority(999.0)
I hope this scenario help someone: I had two constraints, that they were opposite to each other, I mean they couldn't be satisfied in the same time, in interface builder one of them had 1000 priority and other had less than 1000 priority. when I changed them in the code, I had this error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Mutating a priority from required to not on an installed constraint (or vice-versa) is not supported. You passed priority 250 and the existing priority was 1000.'
then I just initialized them in viewDidLoad function with .defaultHigh and .defaultLow values and this fixed my problem.
As stated in NSLayoutConstraint class reference:
Priorities may not change from nonrequired to required, or from required to nonrequired. An exception will be thrown if a priority of
NSLayoutPriorityRequired
in OS X orUILayoutPriorityRequired
in iOS is changed to a lower priority, or if a lower priority is changed to a required priority after the constraints is added to a view. Changing from one optional priority to another optional priority is allowed even after the constraint is installed on a view.
Use priority 999 instead of 1000. It won't be absolutely required technically speaking, but it'll be a higher priority than anything else.
Now you can , just take the IBOutlet connection for your constraints , then use this code .
self.webviewHeight.priority = UILayoutPriority(rawValue: 1000)