我知道汽车布局链基本上包含3个不同的过程。
我不完全清楚的是-setNeedsLayout
和-setNeedsUpdateConstraints
之间的内在差异。来自Apple Docs:
根据需要在应用程序的主线程上调用此方法 调整视图子视图的布局。这个方法记下了 请求并立即返回。因为这种方法没有 强制立即更新,而是等待下一次更新 循环,您可以使用它来使多个视图的布局无效 在更新任何视图之前。这种行为允许你 将所有布局更新合并到一个更新周期,即 通常更好的表现。
当自定义视图的属性以可能影响的方式更改时 约束,可以调用此方法来指示约束 需要在将来的某个时候进行更新。然后系统将 调用updateConstraints作为其正常布局传递的一部分。更新 在需要之前立即对所有约束确保您 不要在多次更改时不必要地重新计算约束 在布局通行证之间制作你的视图。
当我想在修改约束后为视图设置动画并为我通常调用的更改设置动画:
[UIView animateWithDuration:1.0f delay:0.0f usingSpringWithDamping:0.5f initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self.modifConstrView setNeedsUpdateConstraints];
[self.modifConstrView layoutIfNeeded];
} completion:NULL];
我发现如果我使用-setNeedsLayout
代替-setNeedsUpdateConstraints
,一切都按预期工作,但如果我用-layoutIfNeeded
更改-updateConstraintsIfNeeded
,则动画不会发生。
我试图得出自己的结论:
-updateConstraintsIfNeeded
仅更新约束但不强制布局进入流程,因此原始帧仍然保留-setNeedsLayout
也调用-updateContraints
方法那么什么时候可以使用一个而不是另一个?关于布局方法,我是否需要在约束或父视图上有变化的视图上调用它们?
答案 0 :(得分:253)
您的结论是对的。基本方案是:
setNeedsUpdateConstraints
确保以后拨打updateConstraintsIfNeeded
来电updateConstraints
。setNeedsLayout
确保以后拨打layoutIfNeeded
来电layoutSubviews
。调用layoutSubviews
时,它也会调用updateConstraintsIfNeeded
,因此根据我的经验,很少需要手动调用它。实际上,除了在调试布局时,我从未调用它。
使用setNeedsUpdateConstraints
更新约束的情况非常罕见,objc.io–a must read about autolayouts–says:
如果稍后发生某些变化会使您的某个约束无效,则应立即删除约束并调用setNeedsUpdateConstraints。 实际上,这是您必须触发约束更新传递的唯一情况。
另外,根据我的经验,我从来没有必要使约束无效,也没有在代码的下一行设置setNeedsLayout
,因为新的约束几乎要求新的布局。
经验法则是:
setNeedsLayout
。updateConstraints
方法中的约束(建议更改约束的方法,顺便说一下),请调用{{1}在大多数情况下,setNeedsUpdateConstraints
之后。{/ li>
setNeedsLayout
附加它。此外,在您的动画代码中,我认为layoutIfNeeded
是不需要的,因为约束会在动画之前手动更新,并且动画只会根据旧视图和新视图之间的差异重新布置视图。
答案 1 :(得分:81)
answer by coverback非常正确。但是,我想补充一些其他细节。
以下是解释其他行为的典型UIView循环图:
-setNeedsLayout
代替-setNeedsUpdateConstraints
,一切都按预期工作,但如果我使用-layoutIfNeeded
更改-updateConstraintsIfNeeded
,动画不会发生。 updateConstraints
通常无法做任何事情。它只是解决了在调用layoutSubviews
之前它不会应用它们的约束。因此动画需要调用layoutSubviews
。
不,这不是必要的。如果您的约束未被修改,UIView将跳过对updateConstraints
的调用。您需要显式调用setNeedsUpdateConstraint
来修改流程中的约束。
要拨打updateConstraints
,您需要执行以下操作:
[view setNeedsUpdateConstraints];
[view setNeedsLayout];
[view layoutIfNeeded];