在约束依赖于框架的自定义视图中使用自动布局

我正在编写一个自定义视图,以编程方式初始化。 我重写updateConstraints以添加此视图所需的所有约束。 :

 - (void)updateConstraints { [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]]; [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeTop multiplier:1 constant:0]]; [self.superview addConstraint:[NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.superview attribute:NSLayoutAttributeBottom multiplier:1 constant:0]]; // some more constraints, you get the point self.bottomSpacingConstraint = [NSLayoutConstraint constraintWithItem:self.imageView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeBottom multiplier:1 constant:-(0.2 * CGRectGetHeight(self.bounds))]; [self addConstraint:self.bottomSpacingConstraint]; [super updateConstraints]; } 

问题是self.bounds返回CGRectZero的等价物。 我做了我的研究,根据这objc.io文章 ,这是预期的框架不会被设置,直到layoutSubviews被调用。 它也提到

要强制系统立即更新视图树的布局,可以调用layoutIfNeeded / layoutSubtreeIfNeeded (分别在iOS和OS X上)。 如果您的后续步骤依赖最新的视图框架,这可能会有所帮助。

但是,当我补充

 [self setNeedsLayout]; [self layoutIfNeeded]; 

updateConstraints设置self.bottomSpacingConstraint之前,我仍然得到一个CGRectZero框架。 根据objc.io文章(和这个答案 ),这些方法应该触发布局和更新框架。

任何人都可以点亮如何使这一切工作? 我对这个解决scheme感兴趣,并且解释了什么导致了哪些与布局相关的方法被调用(例如,在layoutSubviews中改变现有约束的常量导致setNeedsUpdateConstraints被调用,然后触发updateConstraints并导致约束要多次添加)。

我敢肯定,你不能或不应该从updateConstraints调用layoutIfNeeded 。 更新约束是在布局周期的早期部分,所以我不认为它会产生效果。

在你的情况下,解决scheme将检查layoutSubviews中的依赖于框架的约束的constant属性,如果需要更新,请在那里更新它或调用setNeedsUpdateConstraints (注意导致循环)。

你说更新约束触发器的另一个调用updateConstraints – 这是真的,我认为你是滥用updateConstraints – 它是基于您的视图的内容更改更新约束。 如果它们不存在,只应该添加这些约束。