何时可以激活/取消布局约束?
我已经在IB中设置了多组约束,并且我想以编程方式在它们之间切换,具体取决于某些状态。 有一个constraintsA
一个出口集合,所有这些都被标记为从IB安装,并且一个constraintsB
出口集合,所有这些都在IB中被卸载。
我可以以编程方式在两组之间切换,如下所示:
NSLayoutConstraint.deactivateConstraints(constraintsA) NSLayoutConstraint.activateConstraints(constraintsB)
但是…我无法弄清楚什么时候这样做。 看来我应该能够做到这一点在viewDidLoad
,但我不能得到这个工作。 我已经尝试在设置约束后调用view.updateConstraints()
和view.layoutSubviews()
,但无济于事。
我发现,如果我在viewDidLayoutSubviews
设置约束,一切都按预期工作。 我想我想知道两件事情…
- 为什么我得到这种行为?
- 是否有可能激活/停用viewDidLoad约束?
我激活和取消激活NSLayoutConstraints
,我没有任何问题。 所以它工作。 在您的应用程序和我的设置之间必须有一个区别:-)
我只是描述我的设置 – 也许它可以给你一个主angular:
- 我为所有需要激活/停用的约束设置了
@IBOutlets
。 - 在
ViewController
,我将约束保存到不弱的类属性中。 这样做的原因是我发现在禁用一个约束之后,我无法重新激活它 – 这是零。 所以,它被取消时似乎被删除。 - 我不像你那样使用
NSLayoutConstraint.deactivate/activate
,我使用constraint.active = YES
/NO
来代替。 - 设置约束后,我调用
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视图时,按顺序调用以下生命周期方法:
- 的loadView
- viewDidLoad中
- viewWillAppear中
- viewWillLayoutSubviews
- viewDidLayoutSubviews
- viewDidAppear
现在你的问题。
- 为什么我得到这种行为?
答案:因为当你尝试在viewDidLoad
设置视图的约束时,视图没有边界,因此不能设置约束。 只有在viewDidLayoutSubviews
之后,视图的界限才会被确定下来。
- 是否有可能激活/停用viewDidLoad约束?
答:不可以。