【发布时间】:2009-07-25 20:16:02
【问题描述】:
layoutIfNeeded 何时以及如何使用?我知道当我们更改视图的布局时,我们可以调用setNeedsLayout 来更新布局,但不确定何时应该使用layoutIfNeeded。
注意:我在实际代码中使用了layoutIfNeeded,但忘记了它是在什么上下文中使用的。
【问题讨论】:
layoutIfNeeded 何时以及如何使用?我知道当我们更改视图的布局时,我们可以调用setNeedsLayout 来更新布局,但不确定何时应该使用layoutIfNeeded。
注意:我在实际代码中使用了layoutIfNeeded,但忘记了它是在什么上下文中使用的。
【问题讨论】:
layoutIfNeeded 强制接收器在需要时立即布局其子视图。
假设你已经覆盖了layoutSubviews,并且UIKit 认为你的视图出于某种原因需要布局(例如,你在处理某些用户操作时调用了setNeedsLayout)。然后,您的自定义 layoutSubviews 方法将立即被调用,而不是在常规 UIKit 运行循环事件序列中通常调用它时(在事件处理之后,但在 drawRect: 之前)。
您可能需要在单个运行循环中调用layoutIfNeeded 的示例:
setNeedsLayout 以便稍后调用layoutSubviews。layoutSubviews 中的表格视图执行一些自定义大小调整,从而更改表格视图的大小。问题是当控制器要求表格视图滚动时(第 2 步),表格视图的边界已经过时。更新的边界稍后将仅在表视图上设置(步骤 3)。 layoutSubviews 完成后,控制器希望表格视图滚动到的内容实际上可能不可见。一个解决方案是控制器在它知道这可能发生的情况下调用layoutIfNeeded。
【讨论】:
现在可以通过引用更新周期来描述这两种方法之间的区别。
UIView 的 setNeedsLayout 方法告诉系统您希望它在更新周期时布局和重绘该视图及其所有子视图。这是一个异步活动,因为该方法完成并立即返回,但直到稍后的时间才会真正发生布局和重绘,并且您不知道更新周期是什么时候。
相比之下,layoutIfNeeded 方法是一个同步调用,它告诉系统您想要一个视图及其子视图的布局和重绘,并且您希望它立即完成而无需等待更新周期。当对该方法的调用完成时,布局已经根据在方法调用之前记录的所有更改进行了调整和绘制。
因此,简而言之,layoutIfNeeded 表示请立即更新,而 setNeedsLayout 表示请更新,但您可以等到下一个更新周期。
【讨论】:
LayoutSubViews() - 不要直接调用,而是调用 setNeedsLayout(),如果约束基础未提供预期则覆盖 行为。
SetNeedsLayout()- 调用主线程,等待下一个绘图周期。 有利于性能。
LayoutIfNeeded() - 立即布局子视图。
【讨论】:
setNeedsLayout 实际上调用了 layoutIfNeeded,所以如果你调用 setNeedsDisplay,就没有理由调用 layoutIfNeeded。这样,setNeedsLayout 是一种调用 layoutIfNeeded 的便捷方法,它完成了繁重的工作。
【讨论】: