当使用自动布局(Autolayout)时,在layoutSubviews中添加子视图是否正确?

3

我写了这样的代码,它们很好用

@interface SubView()
@property(nonatomic,strong) UIButton* btn;
@end

@implementation SubView


- (void)layoutSubviews
{
    [super layoutSubviews];
    [self.btn removeFromSuperview];
    self.btn = [UIButton buttonWithType:UIButtonTypeCustom];
    self.btn.backgroundColor = [UIColor greenColor];
    [self.btn setTitle:@"btn" forState:UIControlStateNormal];
    self.btn.translatesAutoresizingMaskIntoConstraints = NO;
    [self addSubview:self.btn];

    NSLayoutConstraint* centerXConstraint = [self.btn.centerXAnchor constraintEqualToAnchor:self.centerXAnchor];
    NSLayoutConstraint* centerYConstraint = [self.btn.centerYAnchor constraintEqualToAnchor:self.centerYAnchor];
    [self addConstraint:centerXConstraint];
    [self addConstraint:centerYConstraint];
}
@end

但是在我看来,当使用Autolayout时,系统会分两步进行布局1 更新Pass 2 布局Pass,而layoutSubviews在第二步(布局Pass)中。
因此,如果我们在layoutSubviews中添加子视图,似乎会更改视图的约束条件,因此我们需要再次进行更新和布局Pass,这将导致无限循环...
但事实上,这段代码运行良好,那么我错在哪里了?

1
添加 subView 不会改变视图的约束条件,因此不会调用 layoutSubviews。然而,在 layoutSubviews 中添加子视图并不是一个好的做法,最好在初始化器中完成。 - Eric Qian
你的意思是centerXConstraint不是view的约束,而是子视图的约束?这样view的layoutSubviews就可以正确布局了。 - ximmyxiao
是的,它只是将按钮与视图的中心对齐,不会影响视图本身的位置/大小。当视图的框架发生变化时,layouSubiviews会被调用,或者如果您执行setNeedsLayoutlayoutIfNeeded手动触发布局。 - Eric Qian
好的,明白了,非常感谢 @EricQian - ximmyxiao
1个回答

6
请记住,layoutSubviews会被多次调用。每次都移除按钮并重新添加它,这有什么意义呢?
另外,layoutSubviews是自动布局系统遵循约束的地方。在layoutSubviews中设置按钮的约束有何意义呢?
即使看起来似乎可以工作,但在layoutSubviews中做的事情都没有意义。请在其他地方完成这个任务,并只执行一次。

谢谢@matt,我看到一些代码(就像我上面发布的那样)在updateConstraints中,所以在updateConstraints中添加/删除子视图也是一个不好的习惯吗? - ximmyxiao
@ximmyxiao 是的。在其他地方做,比如在viewDidLoad中。 - Shebuka
@Shebuka 如果它在自定义的UI视图中,似乎init方法将是唯一一个适合做这些事情的好地方? - ximmyxiao
所以在updateConstraints中添加/删除subView也是一个不好的习惯。重点不在于此。重点是你的代码删除了“btn”视图,然后又将其添加回来。这是愚蠢的部分。你只需要添加一次这个“btn”视图,所以只需添加一次并让它保持不变即可。 - matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接