为什么在-setNeedsLayout -layoutsSubviews方法之后立即执行

时间:2018-10-19 20:46:21

标签: ios autolayout

据我所知,-setNeedsLayout方法仅将标志设置为视图,以在下一个更新周期布置子视图。但是layoutIfNeeded立即调用layoutSubviews方法,而不等待下一个更新周期。

但是,当我在视图上调用-setNeedsLayout时,-layoutSubviews方法将立即执行。据我了解,下一个更新周期应仅在用户交互或视图框架更改时运行。我在某个地方错了吗?也许setNeedsLayout调用更新周期?但当?以及它将如何工作?如果我举3个方法

[self setNeedsLayout];
[self setNeedsUpdateConstraints];
[self setNeedsDisplay];

1 个答案:

答案 0 :(得分:2)

我终于找到了答案。 感谢warren-burton,要共享WWDC演示文稿的链接,确实有帮助。

要回答我的问题,我们首先应该了解什么是“更新周期”。它包括三个部分。约束部分(以更新所有约束),布局部分(以设置所有框架)和绘图部分(以在屏幕上绘制视图)。我的问题引起误解的主要原因是我不知道

更新周期很短

此循环始终在运行。这意味着潜在的更新周期可以每秒运行约120次。如果每秒更新约束,布局和重绘120次,那确实是很差的性能。为避免此问题,有一个标志用于更新布局,更新约束和图形。因此,系统在每个更新周期中检查每个部分是否有必要调用相应的方法。并且updateConstraints()layoutSubviews()drawRect()之类的方法仅在相应的标志打开时调用。

我们可以影响这些标志吗?

是的,我们可以通过setNeedsUpdateConstraints()setNeedsLayout()setNeedsDisplay()方法将所需标志设置为true。因此,如果我们调用setNeedsLayout()方法,则将标志设置为true,然后在下一个更新周期中更新布局。

enter image description here

为什么在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