何时可以激活/取消布局约束?

我已经在IB中设置了多组约束,并且我想以编程方式在它们之间切换,具体取决于某些状态。 有一个constraintsA一个出口集合,所有这些都被标记为从IB安装,并且一个constraintsB出口集合,所有这些都在IB中被卸载。

我可以以编程方式在两组之间切换,如下所示:

 NSLayoutConstraint.deactivateConstraints(constraintsA) NSLayoutConstraint.activateConstraints(constraintsB) 

但是…我无法弄清楚什么时候这样做。 看来我应该能够做到这一点在viewDidLoad ,但我不能得到这个工作。 我已经尝试在设置约束后调用view.updateConstraints()view.layoutSubviews() ,但无济于事。

我发现,如果我在viewDidLayoutSubviews设置约束,一切都按预期工作。 我想我想知道两件事情…

  1. 为什么我得到这种行为?
  2. 是否有可能激活/停用viewDidLoad约束?

我激活和取消激活NSLayoutConstraints ,我没有任何问题。 所以它工作。 在您的应用程序和我的设置之间必须有一个区别:-)

我只是描述我的设置 – 也许它可以给你一个主angular:

  1. 我为所有需要激活/停用的约束设置了@IBOutlets
  2. ViewController ,我将约束保存到不弱的类属性中。 这样做的原因是我发现在禁用一个约束之后,我无法重新激活它 – 这是零。 所以,它被取消时似乎被删除。
  3. 我不像你那样使用NSLayoutConstraint.deactivate/activate ,我使用constraint.active = YES / NO来代替。
  4. 设置约束后,我调用view.layoutIfNeeded()
 override func viewDidLayoutSubviews() { // do it here, after constraints have been materialized } 

也许你可以检查你的@properties ,取而代之的是strong

有时候,因为active = NO set self.yourContraint = nil ,所以你不能再使用self.yourContraint

我相信你遇到的问题是由于约束没有被添加到他们的意见,直到后调用viewDidLoad() 。 你有很多select:

A)您可以将您的布局约束连接到IBOutlet,并通过这些引用在您的代码中访问它们。 由于在viewDidLoad()启动之前连接了sockets,因此约束条件应该是可访问的,您可以继续在那里激活和禁用它们。

B)如果你想使用UIView的constraints()函数来访问各种约束条件,你必须等待viewDidLayoutSubviews()启动并在那里执行,因为这是从nib创build视图控制器后的第一个点,任何安装的约束。 当你完成时,不要忘记调用layoutIfNeeded() 。 这样做的缺点是,如果有任何更改应用,布局传递将执行两次,并且您必须确保不会触发无限循环。

简单的警告:禁用约束不会被 constraints() 方法 返回 这意味着,如果您打算在稍后再次打开约束来禁用某个约束,则需要保留对其的引用。

C)你可以忘记故事板的方法,并手动添加你的约束。 既然你在viewDidLoad()做这个事情,我认为这样做的目的是在对象的整个生命周期内只做一次,而不是随时更改布局,所以这应该是一个可接受的方法。

您还可以将priority属性调整为“启用”和“禁用”(750值为启用,250为禁用)。 出于某种原因,改变active布尔没有任何影响我的用户界面。 不需要layoutIfNeeded ,可以在viewDidLoad或之后的任何时间进行设置和更改。

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

 -(void)viewWillLayoutSubviews{ [super viewWillLayoutSubviews]; self.myLittleConstraint.active = NO; } 

请记住, viewWillLayoutSubviews可以被多次调用,所以在这里不要进行繁重的计算,好吗?

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

我已经发现,只要你在- (void)updateConstraints (objective c)的覆盖中设置每个正常的约束,对初始化使用有效和- (void)updateConstraints约束的strong参考。 而在视图周期的其他地方停用和/或激活你所需要的,然后调用layoutIfNeeded ,你应该没有问题。

最重要的是不要不断重复使用updateConstraints的重写,并且要分开约束的激活,只要在第一次初始化和布局之后调用updateConstraint 。 在视图周期的哪个地方看起来似乎很重要。

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

  1. 的loadView
  2. viewDidLoad中
  3. viewWillAppear中
  4. viewWillLayoutSubviews
  5. viewDidLayoutSubviews
  6. viewDidAppear

现在你的问题。

  1. 为什么我得到这种行为?

答案:因为当你尝试在viewDidLoad设置视图的约束时,视图没有边界,因此不能设置约束。 只有在viewDidLayoutSubviews之后,视图的界限才会被确定下来。

  1. 是否有可能激活/停用viewDidLoad约束?

答:不可以。