我知道自动布局链基本上包括3个不同的过程。
更新的约束
布局视图(这里是我们得到帧计算的地方)
显示
我不太清楚的是-setNeedsLayout和-setNeedsUpdateConstraints之间的内在区别。来自Apple Docs:
setNeedsLayout
Call this method on your application’s main thread when you want to
adjust the layout of a view’s subviews. This method makes a note of
the request and returns immediately. Because this method does not
force an immediate update, but instead waits for the next update
cycle, you can use it to invalidate the layout of multiple views
before any of those views are updated. This behavior allows you to
consolidate all of your layout updates to one update cycle, which is
usually better for performance.
setNeedsUpdateConstraints
当您的自定义视图的属性以一种会影响
约束,您可以调用此方法来指示约束
需要在将来的某个时候进行更新。系统将会
调用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方法
那么什么时候用一种代替另一种合适呢?关于布局方法,我需要在约束发生变化的视图或父视图上调用它们吗?
你的结论是正确的。基本方案为:
setNeedsUpdateConstraints确保未来对updateConstraintsIfNeeded的调用会调用updateConstraints。
setNeedsLayout确保将来调用layoutIfNeeded时调用layoutSubviews。
当layoutSubviews被调用时,它也调用updateConstraintsIfNeeded,所以在我的经验中很少需要手动调用它。事实上,除了在调试布局时,我从来没有调用过它。
使用setNeedsUpdateConstraints来更新约束也是相当罕见的,objc。io -关于自动布局的必读内容-说:
如果后来发生了一些变化,使某个约束失效,您应该立即删除该约束并调用setNeedsUpdateConstraints。事实上,这是您必须触发约束更新传递的唯一情况。
此外,根据我的经验,我从来没有使约束无效,也没有在下一行代码中设置setNeedsLayout,因为新的约束在很大程度上要求新的布局。
经验法则是:
如果直接操作约束,则调用setNeedsLayout。
如果你改变了一些条件(如偏移量或smth),这将改变你重写的updateConstraints方法(一个建议的方式来改变约束,顺便说一句),调用setNeedsUpdateConstraints,大多数情况下,setNeedsLayout之后。
如果你需要上述任何一项措施立即生效,例如:当你需要在布局传递后学习新的帧高度时,使用layoutIfNeeded附加它。
同样,在你的动画代码中,我认为setNeedsUpdateConstraints是不必要的,因为约束是手动更新之前的动画,动画只是重新布局的基础上,新旧之间的差异。
coverback的答案是非常正确的。但是,我想补充一些细节。
下面是一个典型的UIView循环图,它解释了其他行为:
我发现,如果我使用-setNeedsLayout而不是-setNeedsUpdateConstraints一切工作如预期,但如果我改变-layoutIfNeeded与-updateConstraintsIfNeeded,动画不会发生。
updateConstraints通常不做任何事情。它只是解决约束,直到layoutSubviews被调用才应用它们。动画需要调用layoutSubviews。
setNeedsLayout也调用-updateContraints方法
不,这没有必要。如果你的约束没有被修改,UIView将跳过调用updateConstraints。您需要显式地调用setNeedsUpdateConstraint来修改流程中的约束。
为了调用updateConstraints你需要做以下:
[view setNeedsUpdateConstraints];
[view setNeedsLayout];
[view layoutIfNeeded];
你的结论是正确的。基本方案为:
setNeedsUpdateConstraints确保未来对updateConstraintsIfNeeded的调用会调用updateConstraints。
setNeedsLayout确保将来调用layoutIfNeeded时调用layoutSubviews。
当layoutSubviews被调用时,它也调用updateConstraintsIfNeeded,所以在我的经验中很少需要手动调用它。事实上,除了在调试布局时,我从来没有调用过它。
使用setNeedsUpdateConstraints来更新约束也是相当罕见的,objc。io -关于自动布局的必读内容-说:
如果后来发生了一些变化,使某个约束失效,您应该立即删除该约束并调用setNeedsUpdateConstraints。事实上,这是您必须触发约束更新传递的唯一情况。
此外,根据我的经验,我从来没有使约束无效,也没有在下一行代码中设置setNeedsLayout,因为新的约束在很大程度上要求新的布局。
经验法则是:
如果直接操作约束,则调用setNeedsLayout。
如果你改变了一些条件(如偏移量或smth),这将改变你重写的updateConstraints方法(一个建议的方式来改变约束,顺便说一句),调用setNeedsUpdateConstraints,大多数情况下,setNeedsLayout之后。
如果你需要上述任何一项措施立即生效,例如:当你需要在布局传递后学习新的帧高度时,使用layoutIfNeeded附加它。
同样,在你的动画代码中,我认为setNeedsUpdateConstraints是不必要的,因为约束是手动更新之前的动画,动画只是重新布局的基础上,新旧之间的差异。