Autolayout和编程约束:如何处理updateConstraints多次触发?

以编程方式创build布局时,我遵循Apple的build议:override -updateConstraints,添加自定义约束,并且在子视图添加到视图中时调用-setNeedsUpdateConstraints。 我的典型设置如下所示:

- (void)setupViews { //Style View //Add gesture recognizers //Add Subviews [self setNeedsUpdateConstraints]; } - (void)updateConstraints { //Add custom constraints [super updateConstraints]; } 

问题

在某些情况下,多次触发-updateConstraints(例如,当一个视图的控制器被呈现或推动w /animation时)。 这里的问题是添加的每个约束被重新添加。 当试图按需改变增加的约束的常量时,这成为一个严重的问题,因为原来的约束有两个随后相互冲突。 我想,即使你在创造它们之后没有操纵约束条件,那么你看起来也不是很好。

潜在的解决scheme

1 – 删除影响视图的所有约束,然后在-updateConstraints中应用它们:

  - (void)updateConstraints { //Remove all constraints affecting view & subviews //Add custom constraints [super updateConstraints]; } 

2 – 在添加自定义约束之前,根据它设置布局标志并进行检查:

 - (void)updateConstraints { if (self.didAddConstraints) { [super updateConstraints]; return; } //Add custom constraints self.didAddConstraints = YES; [super updateConstraints]; } 

3 – 不要担心加倍约束,只要需要更改常量,只需在重新添加之前删除该约束。

3 – 我没有想到的东西真棒。


这里最好的做法是什么?

简答题:潜在的解决scheme2。

当布局变得更加复杂时,去除和重新应用所有限制条件可能变得昂贵。 另外,如果你的布局是有状态的,你会遇到更多的问题。

加倍约束的效率非常低,您永远无法知道updateConstraints可能会被调用多less次。

正如本博文所示,使用标志是解决这个问题的最简单,最有效的方法。 这就是我自己处理的方式。

作为一个方面说明,你提到那里有一个你还没有想到的真棒方式。 大多数时候,最简单的方法是最棒的方法。 🙂

这种跟踪也可以在初始设置中完成。 在多数情况下。

 override func updateConstraints() { if constraints.count == 0 { let views = ["textField": textField] addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[textField]-0-|", options: [], metrics: nil, views: views)) addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[textField]-0-|", options: [], metrics: nil, views: views)) } super.updateConstraints() }