在以编程方式创build视图时,我应该在哪里设置自动布局约束

我看到设置约束的不同示例。 有些将它们设置在viewDidLoad / loadView (添加子视图之后)。 其他人在方法updateViewConstraints设置它们,它被viewDidAppear调用。

当我尝试在updateViewContraints设置约束时,可能会出现布局跳动,例如视图出现之前的轻微延迟。 另外,如果我使用这种方法,我应该先清除现有的约束,即[self.view [removeConstraints:self.view.constraints]

我在viewDidLoad / loadView设置了我的约束(我的目标是iOS> = 6)。 updateViewConstraints对于改变约束的值是有用的,例如,如果一些约束依赖于屏幕的方向(我知道,这是一个不好的做法),你可以在这个方法中改变它的constant

在会议“iOS和OS X自动布局简介” (WWDC 2012)期间,从39:22开始显示在viewDidLoad添加约束。 我认为这是讲课过程中所说的那些东西之一,但是并不在文件中。

更新:我注意到在视图控制器资源pipe理中设置约束的提及:

如果您希望以编程方式创build视图,而不是使用故事板,则可以通过覆盖视图控制器的loadView方法来实现。 你的这个方法的实现应该做到以下几点:

(……)

3.如果您正在使用自动布局,请为您刚创build的每个视图指定足够的约束以控制视图的位置和大小 。 否则,实现viewWillLayoutSubviewsviewDidLayoutSubviews方法来调整视图层次结构中子视图的框架。 请参阅“调整视图控制器视图的大小”。

更新2 :在WWDC 2015期间, 苹果公司给出了 updateConstraintsupdateViewConstraints推荐用法的新解释 :

真的,所有这一切都是视图有机会在下一次布局过程中及时更改约束的一种方式,但实际上通常并不需要。

所有的初始约束设置都应该在Interface Builder内部完成。

或者如果你真的觉得你需要以编程的方式分配你的约束,像viewDidLoad这样的地方会好很多。

更新约束实际上只是需要定期重复的工作。

而且,当你发现需要的时候改变约束条件是非常简单的。 而如果将逻辑从与其相关的其他代码中分离出来,并将其移入一个单独的方法,稍后再执行,则代码变得难以遵循,因此您将难以维护,其他人理解起来会困难得多。

那么你什么时候需要使用更新约束?

那么,它归结为性能。

如果你发现只是改变你的约束是太慢,那么更新约束可能能够帮助你。

事实certificate,在更新约束中更改约束实际上比在其他时间更改约束更快。

其原因是因为引擎能够把所有在这个过程中发生的约束变化视为一个批次。

我build议创build一个BOOL并将其设置在UIView的-updateViewConstraints (或-updateViewConstraints ,UIViewController)中。

-[UIView updateConstraints] :(苹果文档)

自定义视图设置约束本身应该通过重写此方法来实现。

在视图的生命周期中,可以多次调用-updateViewConstraints-updateViewConstraints 。 (例如,在一个视图上调用setNeedsUpdateConstraints会触发这个事情)。因此,您需要确保阻止创build和激活重复的约束 – 使用BOOL只执行一次约束设置,或者通过创build在创build和激活新的限制之前,确保停用/删除现有的限制条件。

例如:

  - (void)updateConstraints { // for view controllers, use -updateViewConstraints if (!_hasLoadedConstraints) { _hasLoadedConstraints = YES; // create your constraints } [super updateConstraints]; } 

欢呼@fresidue在评论中指出,苹果的文档build议把super作为最后一步。 如果在更改某些约束之前调用super ,则可能会遇到运行时exception(崩溃)。

我有这个解决scheme来改变在故事板中的人加载之前的约束。 该解决scheme删除视图加载后的任何滞后。

 -(void)updateViewConstraints{ dispatch_async(dispatch_get_main_queue(), ^{ //Modify here your Constraint -> Activate the new constraint and deactivate the old one self.yourContraintA.active = true; self.yourContraintB.active= false; //ecc.. }); [super updateViewConstraints]; // This must be the last thing that you do here -> if! ->Crash! } 

你可以在viewWillLayoutSubviews中设置它们:

  override func viewWillLayoutSubviews() { if(!wasViewLoaded){ wasViewLoaded = true //update constraint //also maybe add a subview } } 

在视图中做了布局子视图方法

 override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() }