当以编程方式创建布局时,我遵循Apple的建议:覆盖-updateConstraints,添加自定义约束,并在将子视图添加到视图后调用-setNeedsUpdateConstraints。我的典型设置如下:
- (void)setupViews
{
//Style View
//Add gesture recognizers
//Add Subviews
[self setNeedsUpdateConstraints];
}
- (void)updateConstraints
{
//Add custom constraints
[super updateConstraints];
}
问题
有时会多次触发-updateConstraints(例如,当动画呈现或推动视图的控制器时)。这里的问题是添加的每个约束都被重新添加。当尝试按需更改添加约束的常量时,这成为一个严重的问题,因为有两个原始约束随后相互冲突。我想,即使你在创造它们之后没有操纵约束,也要加倍你看起来不那么好。
潜在解决方案
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 - 我想不到的东西很棒。
这里最好的做法是什么?
答案 0 :(得分:17)
简答:潜在的解决方案编号2.
随着布局变得更加复杂,删除和重新应用所有约束可能会变得昂贵。此外,如果您的布局是有状态的,那么您会遇到更多问题。
加倍约束是非常低效的,你永远不知道可以调用多少次updateConstraints
。
正如this blog post所示,使用标志是处理此问题的最简单,最有效的方法。这就是我自己处理它的方式。
作为旁注,你提到你现在还没有想到的那种令人敬畏的方式。大多数时候,最简单的方式是最棒的方式。 :)
答案 1 :(得分:0)
对于初始设置,也可以进行这种跟踪。在大多数情况下。
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()
}