据我所知,-setNeedsLayout方法仅向 View 设置标志,以便在下一个更新周期布局 subview 。但是layoutIfNeeded会立即调用layoutSubviews方法,而不是等待下一个更新周期。
但是当我在 View 上调用 -setNeedsLayout 时,-layoutSubviews 方法会立即执行。据我了解,下一个更新周期应该仅在用户交互或 View 的框架更改时运行。我有什么地方说错了吗?也许 setNeedsLayout 调用更新周期?但当?它将如何运作?例如,如果我调用 3 个方法
[self setNeedsLayout];
[self setNeedsUpdateConstraints];
[self setNeedsDisplay];
最佳答案
我终于找到答案了。 感谢warren-burton ,分享一下 WWDC 演示的链接,真的很有帮助。
要回答我的问题,我们首先应该了解什么是“更新周期”。它由三部分组成。约束部分(更新所有约束),布局部分(设置所有框架)和绘图部分(在屏幕上绘制 View )。我的问题被误解的主要原因是我不知道
更新周期是一个循环
该循环始终运行。这意味着潜在的更新周期每秒可以运行大约 120 次。如果我们每秒更新约束、布局和重绘 120 次,那性能真的很差。为了避免这个问题,有一个标志来更新布局、更新约束和绘图。因此,每个更新周期系统都会检查每个部分是否需要调用相应的方法。 updateConstraints()
、layoutSubviews()
和 drawRect()
等方法仅在相应标志打开时调用。
我们可以影响这些标志吗?
是的,我们可以通过setNeedsUpdateConstraints()
、setNeedsLayout()
和setNeedsDisplay()
方法将needed标志设置为true。因此,如果我们调用 setNeedsLayout()
方法,该标志将设置为 true,并且布局将在下一个更新周期中更新。
为什么在setNeedsLayout
layoutsSubviews
方法之后立即执行
它永远不会立即执行。仅在用户看来,更新周期在调用 setNeedsLayout 后立即运行,因为更新周期运行得非常快且频繁。 需要理解的一个很好的例子是不断变化的约束常数。
print(label.frame.height) // 100
labelHeightConstraint.constant = 200
print(label.frame.height) // 100
更改约束后,系统会重新计算帧并调用setNeedsLayout()
在下一个更新周期更新帧。如果打印帧的高度,它会是旧的,因为更新周期还没有发生。要查看计算出的帧,您应该通过 layoutIfNeeded()
方法立即强制调用该方法
print(label.frame.height) // 100
labelHeightConstraint.constant = 200
layoutIfNeeded()
print(label.frame.height) // 200
关于ios - 为什么-setNeedsLayout -layoutsubviews方法之后立即执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52899704/