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

Hei*_*erg 78 cocoa-touch ios autolayout

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

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

Are*_*lko 103

我在viewDidLoad/中设置了约束loadView(我的目标是iOS> = 6).updateViewConstraints对于更改约束的值很有用,例如,如果某些约束取决于屏幕的方向(我知道,这是一种不好的做法),您可以constant在此方法中更改它.

"从iOS和OS X自动布局简介"(WWDC 2012)会议期间,从39:22开始,viewDidLoad显示了添加约束.我认为这是讲座中所说的那些事情之一,但没有落在文档中.

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

如果您希望以编程方式创建视图,而不是使用故事板,则可以通过覆盖视图控制器的loadView 方法来实现.您对此方法的实现应执行以下操作:

(......)

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

更新2:在2015年的WWDC 苹果给予了新的解释updateConstraintsupdateViewConstraints推荐的用法:

实际上,所有这些都是让视图有机会及时更改约束以便下一次布局传递的方法,但实际上通常并不需要.

理想情况下,所有初始约束设置都应该在Interface Builder中进行.

或者,如果您确实发现需要以编程方式分配约束,那么像viewDidLoad这样的地方要好得多.

更新约束实际上只适用于需要定期重复的工作.

此外,当您发现需要这样做时,更改约束是非常简单的; 然而,如果你将这个逻辑与其他与之相关的代码区分开来,并将它移动到一个稍后执行的单独方法中,那么你的代码将变得更加难以理解,因此你将难以维护,其他人理解起来会困难得多.

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

嗯,归结为性能.

如果您发现仅仅更改约束的速度太慢,那么更新约束可能会帮助您解决问题.

事实证明,更新约束内的约束实际上比在其他时间更改约束更快.

原因是因为引擎能够将此传递中发生的所有约束更改视为批处理.

  • 我认为视图应该负责约束,而不是视图控制器.在很多情况下,视图控制器甚至不知道视图中的所有元素是什么(例如表视图单元格中的静态标签). (4认同)
  • 为什么在`updateViewConstraints`中更改约束是一种不好的做法? (3认同)
  • +1为此作为最佳答案.Apple将loadView规定为设置初始约束的正确位置,这在updateConstraints方法中不需要额外的BOOL标志(这看起来很简陋). (2认同)

Boo*_*ger 33

我建议创建一个BOOL并在-updateConstraintsUIView中设置它们(或者-updateViewConstraints,对于UIViewController).

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

自己设置约束的自定义视图应该通过覆盖此方法来实现.

双方-updateConstraints-updateViewConstraints可能视图的一生中多次调用.(例如,调用setNeedsUpdateConstraints视图会触发这种情况发生.)因此,您需要确保阻止创建和激活重复约束 - 使用BOOL仅执行一次约束设置,或者确保在创建和激活新约束之前停用/删除现有约束.

例如:

  - (void)updateConstraints {  // for view controllers, use -updateViewConstraints

         if (!_hasLoadedConstraints) {
              _hasLoadedConstraints = YES;
             // create your constraints
         }
         [super updateConstraints];
    }
Run Code Online (Sandbox Code Playgroud)

在评论中向@fresidue干杯,指出Apple的文档建议将调用super作为最后一步.如果super在更改某些约束之前调用,则可能会遇到运行时异常(崩溃).

  • 我不确定它是否有实际意义,但文档说'重要:调用[super updateConstraints]作为实现的最后一步. (6认同)
  • @cocoanutmobile另外请注意,这里的BOOL标志不阻止系统调用`-updateConstraints`或任何东西 - 它仍然会被调用,你还叫`[超级updateConstraints]`. (2认同)

Blu*_*ing 5

这应该在 ViewDidLoad 中完成,根据 Apple 的 WWDC 视频和文档。

不知道为什么人们推荐 updateConstraints。如果您在 updateConstraints 中这样做,您将遇到 NSAutoresizingMaskLayoutConstraint 与自动调整大小的问题,因为您的视图已经考虑了自动遮罩。您需要在 updateConstraints 中删除它们才能工作。

UpdateConstraints 应该是这样的,当您需要“更新”它们、对初始设置进行更改等时。