setNeedsLayout 与 setNeedsUpdateConstraints 和 layoutIfNeeded 与 updateConstraintsIfNeeded [英] setNeedsLayout vs. setNeedsUpdateConstraints and layoutIfNeeded vs updateConstraintsIfNeeded

查看:27
本文介绍了setNeedsLayout 与 setNeedsUpdateConstraints 和 layoutIfNeeded 与 updateConstraintsIfNeeded的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道自动布局链基本上包含 3 个不同的过程.

I know that the auto layout chain consists in basically 3 different process.

  1. 更新约束
  2. 布局视图(这里是我们计算帧的地方)
  3. 显示

我不太清楚的是 -setNeedsLayout-setNeedsUpdateConstraints 之间的内在区别.来自 Apple 文档:

What's is not totally clear to me is the inner difference between -setNeedsLayout and -setNeedsUpdateConstraints. From 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 作为其正常布局传递的一部分.更新中就在需要之前一次性全部约束确保您当多个更改发生时,不要不必要地重新计算约束在布局传递之间为您的视图制作.

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.

当我想在修改约束后为视图设置动画并为我通常调用的更改设置动画时:

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];

我发现如果我使用 -setNeedsLayout 而不是 -setNeedsUpdateConstraints 一切都按预期工作,但是如果我更改 -layoutIfNeeded使用 -updateConstraintsIfNeeded,动画不会发生.
我试图做出自己的结论:

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:

  • -updateConstraintsIfNeeded 只更新约束但不强制布局进入流程,因此仍保留原始帧
  • -setNeedsLayout 也调用了 -updateContraints 方法
  • -updateConstraintsIfNeeded only update constraints but doesn't force the layout to come into the process, thus original frames are still preserved
  • -setNeedsLayout calls also -updateContraints method

那么什么时候可以使用一个而不是另一个?关于布局方法,我是否需要在约束发生变化的视图或父视图上调用它们?

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?

推荐答案

你的结论是对的.基本方案是:

  • setNeedsUpdateConstraints 确保将来对 updateConstraintsIfNeeded 的调用调用 updateConstraints.
  • setNeedsLayout 确保将来对 layoutIfNeeded 的调用调用 layoutSubviews.
  • setNeedsUpdateConstraints makes sure a future call to updateConstraintsIfNeeded calls updateConstraints.
  • setNeedsLayout makes sure a future call to layoutIfNeeded calls layoutSubviews.

layoutSubviews 被调用时,它也会调用updateConstraintsIfNeeded,所以在我的经验中很少需要手动调用它.事实上,除了在调试布局时,我从来没有调用过它.

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.

使用 setNeedsUpdateConstraints 更新约束也很少见,objc.io——关于自动布局的必读——说:

Updating constraints using setNeedsUpdateConstraints is pretty rare too, objc.io–a must read about autolayouts–says:

如果稍后发生的更改使您的约束之一无效,您应该立即删除约束并调用 setNeedsUpdateConstraints.事实上,这是您应该触发约束更新传递的唯一情况.

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.

此外,根据我的经验,我从来没有让约束失效,也没有在下一行代码中设置 setNeedsLayout,因为新的约束几乎都在要求一个新的布局.

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.
  • 如果您更改了某些条件(例如偏移量或 smth),这些条件更改您重写的 updateConstraints 方法(顺便说一句,更改约束的推荐方法)中的约束,请调用 setNeedsUpdateConstraints,大多数情况下,setNeedsLayout 之后.
  • 如果您需要上述任何操作立即生效,例如当您需要在布局通过后了解新的框架高度时 - 将其附加 layoutIfNeeded.
  • If you manipulated constraints directly, call 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), call setNeedsUpdateConstraints, and most of the time, setNeedsLayout after that.
  • 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.

另外,在你的动画代码中,我认为 setNeedsUpdateConstraints 是不需要的,因为约束是在动画之前手动更新的,动画只是根据旧的和新的.

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.

这篇关于setNeedsLayout 与 setNeedsUpdateConstraints 和 layoutIfNeeded 与 updateConstraintsIfNeeded的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆