如何在运行时更改约束优先级

我有一个dynamic高度的视图,我试图在运行时改变这个视图的高度优先。

这是我的代码的一部分;

if (index == 0) { surveyViewHeightConstraint.constant = 0; surveyViewHeightConstraint.priority = 1000; } else if (index == 1) { surveyViewHeightConstraint.constant = 163; surveyViewHeightConstraint.priority = 500; } 

我正在改变索引与button的行动。 当我运行这个代码,我得到这个错误:

 *** Assertion failure in -[NSLayoutConstraint setPriority:], /SourceCache/Foundation/Foundation-1141.1/Layout.subproj/NSLayoutConstraint.m:174 

我在这里犯的错误是什么?

正如NSLayoutConstraint类参考所述 :

优先级可能不会从非需求变为需要,或从需求变为不需要。 如果将iOS中的NSLayoutPriorityRequired或iOS中的NSLayoutPriorityRequired的优先级更改为较低的优先级,或者将约束添加到视图后更低的优先级更改为所需的优先级,则会引发exception。 即使在视图上安装约束之后,仍然允许从一个可选优先级更改为另一个可选优先级。

使用优先级999而不是1000.这在技术上不是绝对要求的,但是它比其他任何东西都要高。

我想对Cyrille的答案做一个小的补充。

如果您在代码中创build约束,请确保在使其处于活动状态之前设置其优先级。 例如:

 surveyViewHeightConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeHeight multiplier:1 constant:0]; surveyViewHeightConstraint.active = YES; surveyViewHeightConstraint.priority = 999; 

这会导致运行时exception。

不支持将所需优先级从不需要安装到已安装的约束(反之亦然)。

正确的顺序是:

 surveyViewHeightConstraint.priority = 999; surveyViewHeightConstraint.active = YES; 

我们一直处理的方式是不改变约束常数,只是优先级。 例如,在你的情况下有两个高度限制。

  heightConstraintOne (who's height is set in the storyboard at 150, and priority set at 750) heightConstraintTwo (who's height is set in the storyboard at 0, and priority set at 250) 

如果你想隐藏视图,你:

 heightConstraintTwo.priority = 999; 

同样,如果你想显示视图:

 heightConstraintTwo.priority = 250; 

根据UIKit Module内的NSLayoutConstraints class

如果约束的优先级小于UILayoutPriorityRequired,那么它是可选的。 较低的优先级约束之前满足较高的优先级约束 约束的满足并非全部或没有。 如果一个约束“a == b”是可选的,那意味着我们将尝试最小化“abs(ab)”。 该属性只能作为初始设置的一部分或可选时进行修改。 约束添加到视图后,如果优先级从/更改为NSLayoutPriorityRequired,则会引发exception。

示例: – 各种优先级的UIButton约束 –

  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]) }