ios 我什么时候可以激活/停用布局约束?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27494542/
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
When can I activate/deactivate layout constraints?
提问by tybro0103
I've set up multiple sets of constraints in IB, and I'd like to programmatically toggle between them depending on some state. There's a constraintsA
outlet collection all of which are marked as installed from IB, and a constraintsB
outlet collection all of which are uninstalled in IB.
我在 IB 中设置了多组约束,我想根据某些状态以编程方式在它们之间切换。有一个constraintsA
出口集合,所有这些集合都标记为从 IB 安装,一个constraintsB
出口集合,所有这些集合都在 IB 中卸载。
I can programmatically toggle between the two sets like so:
我可以像这样以编程方式在两组之间切换:
NSLayoutConstraint.deactivateConstraints(constraintsA)
NSLayoutConstraint.activateConstraints(constraintsB)
But... I can't figure out whento do that. It seems like I should be able to do that once in viewDidLoad
, but I can't get that to work. I've tried calling view.updateConstraints()
and view.layoutSubviews()
after setting the constraints, but to no avail.
但是......我不知道什么时候这样做。似乎我应该能够做到这一点viewDidLoad
,但我无法让它发挥作用。我已经打过电话view.updateConstraints()
,并view.layoutSubviews()
设置约束条件之后,但无济于事。
I did find that if I set the constraints in viewDidLayoutSubviews
everything works as expected. I guess I'd like to know two things...
我确实发现,如果我在viewDidLayoutSubviews
所有事情中都设置了约束,就会按预期工作。我想我想知道两件事......
- Why am I getting this behavior?
- Is it possible to activate/deactivate constraints from viewDidLoad?
- 为什么我会出现这种行为?
- 是否可以从 viewDidLoad 激活/停用约束?
回答by Joachim B?ggild
I activate and deactivate NSLayoutConstraints
in viewDidLoad
, and I do not have any problems with it. So it does work. There must be a difference in setup between your app and mine :-)
我激活和停用NSLayoutConstraints
的viewDidLoad
,和我没有任何问题,它。所以它确实有效。您的应用程序和我的应用程序之间的设置必须有所不同:-)
I'll just describe my setup - maybe it can give you a lead:
我将只描述我的设置 - 也许它可以给你一个线索:
- I set up
@IBOutlets
for all the constraints that I need to activate/deactivate. - In the
ViewController
, I save the constraints into class properties that are not weak. The reason for this is that I found that after deactivating a constraint, I could not reactivate it - it was nil. So, it seems to be deleted when deactivated. - I do not use
NSLayoutConstraint.deactivate/activate
like you do, I useconstraint.active = YES
/NO
instead. - After setting the constraints, I call
view.layoutIfNeeded()
.
- 我设置了
@IBOutlets
激活/停用所需的所有约束。 - 在 中
ViewController
,我将约束保存到不弱的类属性中。这样做的原因是我发现在取消激活一个约束后,我无法重新激活它——它是零。因此,它似乎在停用时被删除。 - 我
NSLayoutConstraint.deactivate/activate
不像你那样使用,我用constraint.active = YES
/NO
代替。 - 设置约束后,我调用
view.layoutIfNeeded()
.
回答by Leo
Maybe you could check your @properties
, replace weak
with strong
.
也许你可以检查你的@properties
,替换weak
为strong
.
Sometimes it because active = NO
set self.yourConstraint = nil
, so that you couldn't use self.yourConstraint
again.
有时是因为active = NO
set self.yourConstraint = nil
,所以你不能self.yourConstraint
再次使用。
回答by Tony Swiftguy
override func viewDidLayoutSubviews() {
// do it here, after constraints have been materialized
}
回答by Ash
I believe the problem you are experiencing is due to constraints not being added to their views until AFTER viewDidLoad()
is called. You have a number of options:
我相信您遇到的问题是由于在viewDidLoad()
调用AFTER 之前没有将约束添加到他们的视图中。您有多种选择:
A)You can connect your layout constraints to an IBOutlet and access them in your code by these references. Since the outlets are connected before viewDidLoad()
kicks off, the constraints should be accessible and you can continue to activate and deactivate them there.
A)您可以将您的布局约束连接到 IBOutlet 并通过这些引用在您的代码中访问它们。由于插座在viewDidLoad()
开始之前已连接,因此应该可以访问约束,您可以继续在那里激活和停用它们。
B)If you wish to use UIView's constraints()
function to access the various constraints you must wait for viewDidLayoutSubviews()
to kick off and do it there, since that is the first point after creating a view controller from a nib that it will have any installed constraints. Don't forget to call layoutIfNeeded()
when you're done. This does have the disadvantage that the layout pass will be performed twice if there are any changes to apply and you must ensure that there is no possibility that an infinite loop will be triggered.
B)如果您希望使用 UIView 的constraints()
函数来访问各种约束,您必须等待viewDidLayoutSubviews()
启动并在那里执行,因为这是从笔尖创建视图控制器后的第一点,它将具有任何已安装的约束。完成后不要忘记打电话layoutIfNeeded()
。这确实有一个缺点,如果要应用任何更改,布局过程将执行两次,并且您必须确保不会触发无限循环。
A quick word of warning: disabled constraints are NOT returned by theconstraints()
method! This means if you DO disable a constraint with the intention of turning it back on again later you will need to keep a reference to it.
一个简短的警告:方法不返回禁用的约束constraints()
!这意味着如果您确实禁用了一个约束并打算稍后再次打开它,您将需要保留对它的引用。
C)You can forget about the storyboard approach and add your constraints manually instead. Since you're doing this in viewDidLoad()
I assume that the intention is to only do it once for the full lifetime of the object rather than changing the layout on the fly, so this ought to be an acceptable method.
C)您可以忘记故事板方法并手动添加约束。既然你这样做,viewDidLoad()
我假设目的是在对象的整个生命周期内只做一次,而不是动态更改布局,所以这应该是一种可以接受的方法。
回答by user2387149
You can also adjust the priority
property to "enable" and "disable" them (750 value to enable and 250 to disable for example). For some reason changing the active
BOOL didn't had any effect on my UI. No need for layoutIfNeeded
and can be set and changed at viewDidLoad or any time after that.
您还可以调整priority
属性以“启用”和“禁用”它们(例如,启用 750 值和禁用值 250)。由于某种原因,更改active
BOOL 对我的 UI 没有任何影响。不需要layoutIfNeeded
并且可以在 viewDidLoad 或之后的任何时间进行设置和更改。
回答by Laszlo
The proper time to deactivate unused constraints:
停用未使用约束的适当时间:
-(void)viewWillLayoutSubviews{
[super viewWillLayoutSubviews];
self.myLittleConstraint.active = NO;
}
Keep in mind that viewWillLayoutSubviews
could be called multiple times, so no heavy calculations here, okay?
请记住,viewWillLayoutSubviews
可以多次调用,所以这里没有繁重的计算,好吗?
Note: if you want to reactive some of the constraints later, then always store strong
reference to them.
注意:如果你想稍后响应一些约束,那么总是存储strong
对它们的引用。
回答by Sumeet
When a view is being created the following life cycle methods are called in order:
创建视图时,将按顺序调用以下生命周期方法:
- loadView
- viewDidLoad
- viewWillAppear
- viewWillLayoutSubviews
- viewDidLayoutSubviews
- viewDidAppear
- 加载视图
- 查看已加载
- 视图将出现
- viewWillLayoutSubviews
- viewDidLayoutSubviews
- 视图DidAppear
Now to your questions.
现在回答你的问题。
- Why am I getting this behavior?
- 为什么我会出现这种行为?
Answer: Because when you try to set the constraints on the views in viewDidLoad
the view does not have its bounds, hence constraints cannot be set. It's only after viewDidLayoutSubviews
that the view's bounds are finalized.
答:因为当你试图在viewDidLoad
视图上设置约束时,视图没有其边界,因此无法设置约束。只有在viewDidLayoutSubviews
最终确定视图的边界之后。
- Is it possible to activate/deactivate constraints from viewDidLoad?
- 是否可以从 viewDidLoad 激活/停用约束?
Answer: No. Reason explained above.
答案:否。原因如上所述。
回答by elliotrock
I have found as long as you set up the constraints per normal in the override of - (void)updateConstraints
(objective c), with a strong
reference for the initiality used active and un-active constraints. And elsewhere in the view cycle deactivate and/or activate what you need, then calling layoutIfNeeded
, you should have no issues.
我发现只要您在- (void)updateConstraints
(目标 c)的覆盖中设置每个法线的约束,并strong
参考使用的活动和非活动约束的初始值。在视图循环中的其他地方停用和/或激活您需要的内容,然后调用layoutIfNeeded
,您应该没有问题。
The main thing is not to constantly reuse the override of updateConstraints
and to separate the activations of the constraints, as long as you call updateConstraint
s after your first initialization and layout. It does seem to matter after that where in the view cycle.
主要的是不要不断重用updateConstraints
约束的覆盖和分离约束的激活,只要您updateConstraint
在第一次初始化和布局后调用s 即可。之后在视图周期中的哪个位置似乎很重要。