如何在 运行 时间内更改约束优先级
How can I change constraints priority in run time
我有一个具有动态高度的视图,我正试图在 运行 时间内更改此视图高度优先级。
这是我的部分代码;
if (index == 0) {
surveyViewHeightConstraint.constant = 0;
surveyViewHeightConstraint.priority = 1000;
} else if (index == 1) {
surveyViewHeightConstraint.constant = 163;
surveyViewHeightConstraint.priority = 500;
}
我正在使用按钮操作更改索引。当我 运行 此代码时,出现此错误:
*** Assertion failure in -[NSLayoutConstraint setPriority:], /SourceCache/Foundation/Foundation-1141.1/Layout.subproj/NSLayoutConstraint.m:174
我这里有什么错误?
如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.
使用优先级 999 而不是 1000。从技术上讲,这不是绝对需要的,但它的优先级比其他任何东西都高。
我们一直以来的处理方式是不改变约束常量,只改变优先级。例如,在您的情况下有两个高度限制。
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;
我想对 Cyrille 的回答做一点补充。
如果您在代码中创建约束,请确保在激活之前设置其优先级。例如:
surveyViewHeightConstraint = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.superview
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0];
surveyViewHeightConstraint.active = YES;
surveyViewHeightConstraint.priority = 999;
这将导致 运行 次异常。
Mutating a priority from required to not on an installed constraint (or vice-versa) is not supported.
正确的顺序是:
surveyViewHeightConstraint.priority = 999;
surveyViewHeightConstraint.active = YES;
对于 Swift 版本 4+
constraintName.priority = UILayoutPriority(rawValue: 999)
根据NSLayoutConstraints class
内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.
示例:- 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])
}
Swift版本:
myContraint.priority = UILayoutPriority(999.0)
现在可以了,只需将 IBOutlet 连接作为约束,然后使用此代码。
self.webviewHeight.priority = UILayoutPriority(rawValue: 1000)
我希望这个场景对某人有所帮助:
我有两个约束,它们彼此相反,我的意思是它们不能同时满足,在界面生成器中,其中一个优先级为 1000,另一个优先级小于 1000。当我在代码中更改它们时,我遇到了这个错误:
由于未捕获的异常 'NSInternalInconsistencyException',正在终止应用程序,原因:'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.'
然后我用 .defaultHigh 和 .defaultLow 值在 viewDidLoad 函数中初始化它们,这解决了我的问题。
我遇到了同样的问题。正如上面在 iOS 13 中提到的一些答案,更改优先级可以正常工作,但是在 iOS 12 中它会导致崩溃。
我能够通过在 Storyboard 中将其优先级保留为 1000 的特定约束创建 IBOutlet NSLayoutConstraint 来解决此问题,下面是修复代码。
if (Condition) {
surveyViewHeightConstraint.constant = 0;
surveyViewHeightConstraint.isActive = false;
} else if (index == 1) {
surveyViewHeightConstraint.constant = 163;
surveyViewHeightConstraint.isActive = True;
}
希望对您有所帮助!!!干杯
我有一个具有动态高度的视图,我正试图在 运行 时间内更改此视图高度优先级。
这是我的部分代码;
if (index == 0) {
surveyViewHeightConstraint.constant = 0;
surveyViewHeightConstraint.priority = 1000;
} else if (index == 1) {
surveyViewHeightConstraint.constant = 163;
surveyViewHeightConstraint.priority = 500;
}
我正在使用按钮操作更改索引。当我 运行 此代码时,出现此错误:
*** Assertion failure in -[NSLayoutConstraint setPriority:], /SourceCache/Foundation/Foundation-1141.1/Layout.subproj/NSLayoutConstraint.m:174
我这里有什么错误?
如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.
使用优先级 999 而不是 1000。从技术上讲,这不是绝对需要的,但它的优先级比其他任何东西都高。
我们一直以来的处理方式是不改变约束常量,只改变优先级。例如,在您的情况下有两个高度限制。
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;
我想对 Cyrille 的回答做一点补充。
如果您在代码中创建约束,请确保在激活之前设置其优先级。例如:
surveyViewHeightConstraint = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:self.superview
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0];
surveyViewHeightConstraint.active = YES;
surveyViewHeightConstraint.priority = 999;
这将导致 运行 次异常。
Mutating a priority from required to not on an installed constraint (or vice-versa) is not supported.
正确的顺序是:
surveyViewHeightConstraint.priority = 999;
surveyViewHeightConstraint.active = YES;
对于 Swift 版本 4+
constraintName.priority = UILayoutPriority(rawValue: 999)
根据NSLayoutConstraints class
内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.
示例:- 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])
}
Swift版本:
myContraint.priority = UILayoutPriority(999.0)
现在可以了,只需将 IBOutlet 连接作为约束,然后使用此代码。
self.webviewHeight.priority = UILayoutPriority(rawValue: 1000)
我希望这个场景对某人有所帮助: 我有两个约束,它们彼此相反,我的意思是它们不能同时满足,在界面生成器中,其中一个优先级为 1000,另一个优先级小于 1000。当我在代码中更改它们时,我遇到了这个错误:
由于未捕获的异常 'NSInternalInconsistencyException',正在终止应用程序,原因:'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.'
然后我用 .defaultHigh 和 .defaultLow 值在 viewDidLoad 函数中初始化它们,这解决了我的问题。
我遇到了同样的问题。正如上面在 iOS 13 中提到的一些答案,更改优先级可以正常工作,但是在 iOS 12 中它会导致崩溃。
我能够通过在 Storyboard 中将其优先级保留为 1000 的特定约束创建 IBOutlet NSLayoutConstraint 来解决此问题,下面是修复代码。
if (Condition) {
surveyViewHeightConstraint.constant = 0;
surveyViewHeightConstraint.isActive = false;
} else if (index == 1) {
surveyViewHeightConstraint.constant = 163;
surveyViewHeightConstraint.isActive = True;
}
希望对您有所帮助!!!干杯