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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:01:58  来源:igfitidea点击:

When can I activate/deactivate layout constraints?

iosswiftuiviewautolayoutnslayoutconstraint

提问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 constraintsAoutlet collection all of which are marked as installed from IB, and a constraintsBoutlet 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 viewDidLayoutSubviewseverything works as expected. I guess I'd like to know two things...

我确实发现,如果我在viewDidLayoutSubviews所有事情中都设置了约束,就会按预期工作。我想我想知道两件事......

  1. Why am I getting this behavior?
  2. Is it possible to activate/deactivate constraints from viewDidLoad?
  1. 为什么我会出现这种行为?
  2. 是否可以从 viewDidLoad 激活/停用约束?

回答by Joachim B?ggild

I activate and deactivate NSLayoutConstraintsin 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 :-)

我激活和停用NSLayoutConstraintsviewDidLoad,和我没有任何问题,它。所以它确实有效。您的应用程序和我的应用程序之间的设置必须有所不同:-)

I'll just describe my setup - maybe it can give you a lead:

我将只描述我的设置 - 也许它可以给你一个线索:

  1. I set up @IBOutletsfor all the constraints that I need to activate/deactivate.
  2. 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.
  3. I do not use NSLayoutConstraint.deactivate/activatelike you do, I use constraint.active = YES/NOinstead.
  4. After setting the constraints, I call view.layoutIfNeeded().
  1. 我设置了@IBOutlets激活/停用所需的所有约束。
  2. 在 中ViewController,我将约束保存到不弱的类属性中。这样做的原因是我发现在取消激活一个约束后,我无法重新激活它——它是零。因此,它似乎在停用时被删除。
  3. NSLayoutConstraint.deactivate/activate不像你那样使用,我用constraint.active = YES/NO代替。
  4. 设置约束后,我调用view.layoutIfNeeded().

回答by Leo

Maybe you could check your @properties, replace weakwith strong.

也许你可以检查你的@properties,替换weakstrong.

Sometimes it because active = NOset self.yourConstraint = nil, so that you couldn't use self.yourConstraintagain.

有时是因为active = NOset 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 priorityproperty to "enable" and "disable" them (750 value to enable and 250 to disable for example). For some reason changing the activeBOOL didn't had any effect on my UI. No need for layoutIfNeededand can be set and changed at viewDidLoad or any time after that.

您还可以调整priority属性以“启用”和“禁用”它们(例如,启用 750 值和禁用值 250)。由于某种原因,更改activeBOOL 对我的 UI 没有任何影响。不需要layoutIfNeeded并且可以在 viewDidLoad 或之后的任何时间进行设置和更改。

回答by Laszlo

The proper time to deactivate unused constraints:

停用未使用约束的适当时间:

-(void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];

    self.myLittleConstraint.active = NO;
}

Keep in mind that viewWillLayoutSubviewscould 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 strongreference to them.

注意:如果你想稍后响应一些约束,那么总是存储strong对它们的引用。

回答by Sumeet

When a view is being created the following life cycle methods are called in order:

创建视图时,将按顺序调用以下生命周期方法:

  1. loadView
  2. viewDidLoad
  3. viewWillAppear
  4. viewWillLayoutSubviews
  5. viewDidLayoutSubviews
  6. viewDidAppear
  1. 加载视图
  2. 查看已加载
  3. 视图将出现
  4. viewWillLayoutSubviews
  5. viewDidLayoutSubviews
  6. 视图DidAppear

Now to your questions.

现在回答你的问题。

  1. Why am I getting this behavior?
  1. 为什么我会出现这种行为?

Answer: Because when you try to set the constraints on the views in viewDidLoadthe view does not have its bounds, hence constraints cannot be set. It's only after viewDidLayoutSubviewsthat the view's bounds are finalized.

答:因为当你试图在viewDidLoad视图上设置约束时,视图没有其边界,因此无法设置约束。只有在viewDidLayoutSubviews最终确定视图的边界之后。

  1. Is it possible to activate/deactivate constraints from viewDidLoad?
  1. 是否可以从 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 strongreference 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 updateConstraintsand to separate the activations of the constraints, as long as you call updateConstraints after your first initialization and layout. It does seem to matter after that where in the view cycle.

主要的是不要不断重用updateConstraints约束的覆盖和分离约束的激活,只要您updateConstraint在第一次初始化和布局后调用s 即可。之后在视图周期中的哪个位置似乎很重要。