ios 如何在运行时更改约束优先级
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31186187/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I change constraints priority in run time
提问by Le'Kirdok
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) {
surveyViewHeightConstraint.constant = 0;
surveyViewHeightConstraint.priority = 1000;
} else if (index == 1) {
surveyViewHeightConstraint.constant = 163;
surveyViewHeightConstraint.priority = 500;
}
I am changing index with a button action. When I run this code, I am getting this error:
我正在通过按钮操作更改索引。当我运行此代码时,出现此错误:
*** Assertion failure in -[NSLayoutConstraint setPriority:], /SourceCache/Foundation/Foundation-1141.1/Layout.subproj/NSLayoutConstraint.m:174
What is my mistake in here?
我在这里有什么错误?
回答by Cyrille
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.
优先级不得从非必需变为必需,或从必需变为非必需。如果
NSLayoutPriorityRequired
在 OS X 或UILayoutPriorityRequired
iOS中将优先级更改为较低的优先级,或者在将约束添加到视图后将较低的优先级更改为所需的优先级,则会引发异常。即使在视图上安装了约束之后,也允许从一个可选优先级更改为另一个可选优先级。
Use priority 999 instead of 1000. It won't be absolutely required technically speaking, but it'll be a higher priority than anything else.
使用优先级 999 而不是 1000。从技术上讲,它不是绝对必需的,但它比其他任何东西都具有更高的优先级。
回答by Vipin
I want to make a small addition to Cyrille's answer.
我想对 Cyrille 的回答做一点补充。
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+
对于 Swift 版本 4+
constraintName.priority = UILayoutPriority(rawValue: 999)
回答by Alex
Swift version:
迅捷版:
myContraint.priority = UILayoutPriority(999.0)
回答by J Andrew McCormick
The way we have always handled this is by not changing the constraint constant, just the priority. For example, in your situation have two height constraints.
我们一直处理这个问题的方法是不改变约束常数,只改变优先级。例如,在您的情况下有两个高度限制。
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)
if you want to hide the view, you:
如果你想隐藏视图,你:
heightConstraintTwo.priority = 999;
likewise, if you want to show the view:
同样,如果要显示视图:
heightConstraintTwo.priority = 250;
回答by J Andrew McCormick
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:
我希望这个场景对某人有所帮助:我有两个约束,它们彼此相反,我的意思是它们不能同时满足,在界面构建器中,其中一个优先级为 1000,另一个优先级低于 1000。当我在代码中更改它们时,出现以下错误:
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.'
由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“不支持将优先级从必需的更改为未安装的约束(反之亦然)。您通过了优先级 250,现有的优先级为 1000。
then I just initialized them in viewDidLoad function with .defaultHigh and .defaultLow values and this fixed my problem.
然后我只是用 .defaultHigh 和 .defaultLow 值在 viewDidLoad 函数中初始化它们,这解决了我的问题。
回答by Hyman
According to NSLayoutConstraints class
inside UIKit Module
据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.
如果约束的优先级低于 UILayoutPriorityRequired,则它是可选的。在较低优先级约束之前满足较高优先级约束。约束满足不是全有或全无。如果约束 'a == b' 是可选的,这意味着我们将尝试最小化 'abs(ab)'。此属性只能作为初始设置的一部分或在可选时进行修改。将约束添加到视图后,如果优先级从 NSLayoutPriorityRequired 更改为/更改为 NSLayoutPriorityRequired,则会引发异常。
Example:- UIButton
constraints with various priorities -
示例:-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])
}
回答by Venkat057
I was facing the same issue. As some of the answer mentioned above in iOS 13 changing priority will work fine, However in iOS 12 it will lead to crash.
我面临着同样的问题。由于iOS 13更改优先级中上面提到的一些答案可以正常工作,但是在iOS 12中它会导致崩溃。
I was able to fix this problem by creating IBOutlet NSLayoutConstraint to that specific constraint in Storyboard retaining its priority to 1000, below is the code for fix.
我能够通过在 Storyboard 中为该特定约束创建 IBOutlet NSLayoutConstraint 来解决这个问题,保留其优先级为 1000,下面是修复代码。
if (Condition) {
surveyViewHeightConstraint.constant = 0;
surveyViewHeightConstraint.isActive = false;
} else if (index == 1) {
surveyViewHeightConstraint.constant = 163;
surveyViewHeightConstraint.isActive = True;
}
Hope this helps!!! Cheers
希望这可以帮助!!!干杯
回答by Kishore Kumar
Now you can , just take the IBOutlet connection for your constraints , then use this code .
现在您可以,只需将 IBOutlet 连接用于您的约束,然后使用此代码。
self.webviewHeight.priority = UILayoutPriority(rawValue: 1000)