I know that the auto layout chain consists in basically 3 different process.
我知道汽车布局链基本上由三个不同的过程组成。
- updating constraints
- 更新的约束
- layout views (here is where we get calculation of frames)
- 布局视图(这里是计算帧的地方)
- display
- 显示
What's is not totally clear to me is the inner difference between -setNeedsLayout
and -setNeedsUpdateConstraints
. From Apple Docs:
我不太清楚的是-setNeedsLayout和- setneedsupdateconstr之间的内在差异。从苹果公司文档:
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
When a property of your custom view changes in a way that would impact constraints, you can call this method to indicate that the constraints need to be updated at some point in the future. The system will then call updateConstraints as part of its normal layout pass. Updating constraints all at once just before they are needed ensures that you don’t needlessly recalculate constraints when multiple changes are made to your view in between layout passes.
当自定义视图的属性以影响约束的方式更改时,您可以调用此方法来指示将来某个时候需要更新约束。然后,系统将调用updateconstr作为常规布局传递的一部分。在需要的时候更新约束条件,确保在布局通过时,在对视图进行多次更改时,不需要重新计算约束。
When I want to animate a view after modifying a constraint and animate the changes I usually call for instance:
当我想在修改了约束条件并激活我通常调用的更改之后动画一个视图时:
[UIView animateWithDuration:1.0f delay:0.0f usingSpringWithDamping:0.5f initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
[self.modifConstrView setNeedsUpdateConstraints];
[self.modifConstrView layoutIfNeeded];
} completion:NULL];
I've found out that if I use -setNeedsLayout
instead of -setNeedsUpdateConstraints
everything work as expected, but if I change -layoutIfNeeded
with -updateConstraintsIfNeeded
, the animation won't happen.
I've tried to make my own conclusion:
我发现,如果我使用-setNeedsLayout而不是- setneedsupdateconstrject,一切工作都如预期的那样,但是如果我更改- layoutifneed与- updateconstraintsifneed,动画就不会发生。我试图得出我自己的结论:
-
-updateConstraintsIfNeeded
only update constraints but doesn't force the layout to come into the process, thus original frames are still preserved - - updateconstraintsif只需要更新约束,但不强制布局进入进程,因此原始的框架仍然保留
-
-setNeedsLayout
calls also-updateContraints
method - -setNeedsLayout调用- updatecontr方法
So when is ok to use one instead of the other? and about the layout methods, do I need to call them on the view that has a change in a constraint or on the parent view?
那么什么时候可以用一个代替另一个呢?关于布局方法,我需要在约束发生变化的视图上调用它们还是在父视图上调用它们?
2 个解决方案
#1
239
Your conclusions are right. The basic scheme is:
你的结论是正确的。基本的计划是:
-
setNeedsUpdateConstraints
makes sure a future call toupdateConstraintsIfNeeded
callsupdateConstraints
. - setneedsupdateconstrments确保将来调用updateconstraintsifrequired调用updateconstr。
-
setNeedsLayout
makes sure a future call tolayoutIfNeeded
callslayoutSubviews
. - setNeedsLayout确保将来调用layoutifrequired调用layoutSubviews。
When layoutSubviews
is called, it also calls updateConstraintsIfNeeded
, so calling it manually is rarely needed in my experience. In fact, I have never called it except when debugging layouts.
当调用layoutSubviews时,它还调用updateconstraintsifneed,因此在我的经验中很少需要手动调用它。事实上,除了调试布局之外,我从未调用过它。
Updating constraints using setNeedsUpdateConstraints
is pretty rare too, objc.io–a must read about autolayouts–says:
objc也很少使用setneedsupdateconstr来更新约束。io-a必须读到自述语——说:
If something changes later on that invalidates one of your constraints, you should remove the constraint immediately and call setNeedsUpdateConstraints. In fact, that’s the only case where you should have to trigger a constraint update pass.
如果稍后发生更改,使其中一个约束失效,您应该立即删除该约束,并调用setneedsupdateconstr。实际上,这是惟一需要触发约束更新传递的情况。
In addition, in my experience, I have never had to invalidate constraints, and not set the setNeedsLayout
in the next line of the code, because new constraints pretty much are asking for a new layout.
此外,根据我的经验,我从来没有需要使约束失效,也没有在代码的下一行中设置setNeedsLayout,因为新的约束几乎需要新的布局。
The rules of thumb are:
经验法则是:
- If you manipulated constraints directly, call
setNeedsLayout
. - 如果您直接操作约束,调用setNeedsLayout。
- If you changed some conditions (like offsets or smth) which would change constraints in your overridden
updateConstraints
method (a recommended way to change constraints, btw), callsetNeedsUpdateConstraints
, and most of the time,setNeedsLayout
after that. - 如果您更改了一些条件(比如偏移量或smth),它将改变您重写的updateconstr方法中的约束(一个建议的更改约束的方法,btw),调用setneedsupdateconstr,并且大多数时间,在此之后进行setNeedsLayout。
- If you need any of the actions above to have immediate effect—e.g. when your need to learn new frame height after a layout pass—append it with a
layoutIfNeeded
. - 如果你需要上面的任何一个动作来产生立竿见影的效果。当你需要学习新的框架高度后,布局传递-附加它与一个layoutifneed。
Also, in your animation code, I believe setNeedsUpdateConstraints
is unneeded, since constraints are updated before the animation manually, and the animation only re-lays-out the view based on differences between the old and new ones.
另外,在您的动画代码中,我认为不需要setneedsupdateconstr,因为在动画之前会手动更新约束,动画只根据新旧视图之间的差异重新布局视图。
#2
70
The answer by coverback is pretty correct . However, I would like to add some additional details.
掩盖事实的答案是相当正确的。然而,我想补充一些额外的细节。
Below is the diagram of a typical UIView cycle which explains other behaviors
下面是解释其他行为的典型UIView循环的图表
- I've found out that if I use -setNeedsLayout instead of -setNeedsUpdateConstraints everything work as expected, but if I change -layoutIfNeeded with -updateConstraintsIfNeeded, the animation won't happen.
- 我发现,如果我使用-setNeedsLayout而不是- setneedsupdateconstrouts,那么一切都会按预期工作,但是如果我使用- updateconstraintsifneed更改- layoutifneed,动画就不会发生。
updateConstraints
typically doesn't do anything. It just resolves constraints it doesn't apply them till layoutSubviews
is called. So animation does requires a call to layoutSubviews
.
updateconstr通常什么都不做。它只是解决了在调用layoutSubviews之前没有应用的约束。所以动画需要调用layoutSubviews。
- setNeedsLayout calls also -updateContraints method
- setNeedsLayout调用——updatecontr方法
No this is not necessary. If your constraints haven't been modified UIView will skip call to updateConstraints
. You need to explicitly call setNeedsUpdateConstraint
to modify constraints in the process.
不,这不是必须的。如果您的约束没有被修改,UIView将跳过对updateconstr的调用。您需要显式地调用setNeedsUpdateConstraint来修改流程中的约束。
In order to call updateConstraints
you need to do the following :
为了调用updateconstr,您需要执行以下操作:
[view setNeedsUpdateConstraints];
[view setNeedsLayout];
[view layoutIfNeeded];
#1
239
Your conclusions are right. The basic scheme is:
你的结论是正确的。基本的计划是:
-
setNeedsUpdateConstraints
makes sure a future call toupdateConstraintsIfNeeded
callsupdateConstraints
. - setneedsupdateconstrments确保将来调用updateconstraintsifrequired调用updateconstr。
-
setNeedsLayout
makes sure a future call tolayoutIfNeeded
callslayoutSubviews
. - setNeedsLayout确保将来调用layoutifrequired调用layoutSubviews。
When layoutSubviews
is called, it also calls updateConstraintsIfNeeded
, so calling it manually is rarely needed in my experience. In fact, I have never called it except when debugging layouts.
当调用layoutSubviews时,它还调用updateconstraintsifneed,因此在我的经验中很少需要手动调用它。事实上,除了调试布局之外,我从未调用过它。
Updating constraints using setNeedsUpdateConstraints
is pretty rare too, objc.io–a must read about autolayouts–says:
objc也很少使用setneedsupdateconstr来更新约束。io-a必须读到自述语——说:
If something changes later on that invalidates one of your constraints, you should remove the constraint immediately and call setNeedsUpdateConstraints. In fact, that’s the only case where you should have to trigger a constraint update pass.
如果稍后发生更改,使其中一个约束失效,您应该立即删除该约束,并调用setneedsupdateconstr。实际上,这是惟一需要触发约束更新传递的情况。
In addition, in my experience, I have never had to invalidate constraints, and not set the setNeedsLayout
in the next line of the code, because new constraints pretty much are asking for a new layout.
此外,根据我的经验,我从来没有需要使约束失效,也没有在代码的下一行中设置setNeedsLayout,因为新的约束几乎需要新的布局。
The rules of thumb are:
经验法则是:
- If you manipulated constraints directly, call
setNeedsLayout
. - 如果您直接操作约束,调用setNeedsLayout。
- If you changed some conditions (like offsets or smth) which would change constraints in your overridden
updateConstraints
method (a recommended way to change constraints, btw), callsetNeedsUpdateConstraints
, and most of the time,setNeedsLayout
after that. - 如果您更改了一些条件(比如偏移量或smth),它将改变您重写的updateconstr方法中的约束(一个建议的更改约束的方法,btw),调用setneedsupdateconstr,并且大多数时间,在此之后进行setNeedsLayout。
- If you need any of the actions above to have immediate effect—e.g. when your need to learn new frame height after a layout pass—append it with a
layoutIfNeeded
. - 如果你需要上面的任何一个动作来产生立竿见影的效果。当你需要学习新的框架高度后,布局传递-附加它与一个layoutifneed。
Also, in your animation code, I believe setNeedsUpdateConstraints
is unneeded, since constraints are updated before the animation manually, and the animation only re-lays-out the view based on differences between the old and new ones.
另外,在您的动画代码中,我认为不需要setneedsupdateconstr,因为在动画之前会手动更新约束,动画只根据新旧视图之间的差异重新布局视图。
#2
70
The answer by coverback is pretty correct . However, I would like to add some additional details.
掩盖事实的答案是相当正确的。然而,我想补充一些额外的细节。
Below is the diagram of a typical UIView cycle which explains other behaviors
下面是解释其他行为的典型UIView循环的图表
- I've found out that if I use -setNeedsLayout instead of -setNeedsUpdateConstraints everything work as expected, but if I change -layoutIfNeeded with -updateConstraintsIfNeeded, the animation won't happen.
- 我发现,如果我使用-setNeedsLayout而不是- setneedsupdateconstrouts,那么一切都会按预期工作,但是如果我使用- updateconstraintsifneed更改- layoutifneed,动画就不会发生。
updateConstraints
typically doesn't do anything. It just resolves constraints it doesn't apply them till layoutSubviews
is called. So animation does requires a call to layoutSubviews
.
updateconstr通常什么都不做。它只是解决了在调用layoutSubviews之前没有应用的约束。所以动画需要调用layoutSubviews。
- setNeedsLayout calls also -updateContraints method
- setNeedsLayout调用——updatecontr方法
No this is not necessary. If your constraints haven't been modified UIView will skip call to updateConstraints
. You need to explicitly call setNeedsUpdateConstraint
to modify constraints in the process.
不,这不是必须的。如果您的约束没有被修改,UIView将跳过对updateconstr的调用。您需要显式地调用setNeedsUpdateConstraint来修改流程中的约束。
In order to call updateConstraints
you need to do the following :
为了调用updateconstr,您需要执行以下操作:
[view setNeedsUpdateConstraints];
[view setNeedsLayout];
[view layoutIfNeeded];