How can I change constraints priority in run time

后端 未结 8 1215
一整个雨季
一整个雨季 2020-12-12 16:07

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) {

          


        
相关标签:
8条回答
  • 2020-12-12 16:19

    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])
    
             }  
    
    0 讨论(0)
  • 2020-12-12 16:21

    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)
    
    0 讨论(0)
  • 2020-12-12 16:22

    Swift version:

    myContraint.priority = UILayoutPriority(999.0)
    
    0 讨论(0)
  • 2020-12-12 16:22

    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.

    0 讨论(0)
  • 2020-12-12 16:31

    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 or UILayoutPriorityRequired 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.

    0 讨论(0)
  • 2020-12-12 16:32

    Now you can , just take the IBOutlet connection for your constraints , then use this code .

    self.webviewHeight.priority = UILayoutPriority(rawValue: 1000)
    
    0 讨论(0)
提交回复
热议问题