ios layoutIfNeeded 是如何使用的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1182945/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:12:50  来源:igfitidea点击:

How is layoutIfNeeded used?

iosiphoneuikit

提问by Boon

When and how is layoutIfNeededused? I know that when we change the layout of a view, we can call setNeedsLayoutto update the layout but not sure when layoutIfNeededshould be used.

何时以及如何layoutIfNeeded使用?我知道当我们改变视图的布局时,我们可以调用setNeedsLayout来更新布局但不确定什么时候layoutIfNeeded应该使用。

NOTE: I have layoutIfNeededused in actual code but forgot in what context it was used.

注意:我layoutIfNeeded在实际代码中使用过,但忘记了它是在什么上下文中使用的。

回答by Allen Ding

layoutIfNeededforces the receiver to layout its subviews immediately if required.

layoutIfNeeded如果需要,强制接收器立即布局其子视图。

Suppose you have overridden layoutSubviews, and UIKit feels that your view requires layout for whatever reason (e.g. you called setNeedsLayoutwhen handling some user action). Then, your custom layoutSubviewsmethod will be called immediately instead of when it would normally be called in the regular UIKit run loop event sequence (after event handling, but before drawRect:).

假设您已经覆盖了layoutSubviews,并且 UIKit 认为您的视图出于某种原因需要布局(例如,您setNeedsLayout在处理某些用户操作时调用)。然后,您的自定义layoutSubviews方法将立即被调用,而不是在常规 UIKit 运行循环事件序列中正常调用时(在事件处理之后,但在 之前drawRect:)。

An example of why you might need to call layoutIfNeededwithin a single run loop:

您可能需要layoutIfNeeded在单个运行循环中调用的原因的示例:

  1. You resize a custom view containing a table view with a custom layout. setNeedsLayoutis set so that layoutSubviewswill be called later.
  2. A controller object asks the table view to scroll to some particular cell when handling a user event.
  3. Your custom view performs some custom sizing of the table view in layoutSubviewsthat changes the table view size.
  1. 您调整包含具有自定义布局的表格视图的自定义视图的大小。setNeedsLayout已设置,以便layoutSubviews稍后调用。
  2. 控制器对象在处理用户事件时要求表格视图滚动到某个特定的单元格。
  3. 您的自定义视图对表格视图执行一些自定义大小调整,layoutSubviews从而更改表格视图的大小。

The problem is when the controller asked the table view to scroll (step 2), the table view had bounds that were stale. The updated bounds would only be set on the table view later (step 3). What the controller wanted the table view to scroll to may not actually be visible after layoutSubviewsis done. A solution then would be for the controller to call layoutIfNeededin situations where it knows this might occur.

问题是当控制器要求表格视图滚动时(第 2 步),表格视图的边界已经过时。更新后的边界将稍后仅在表视图上设置(第 3 步)。控制器希望表格视图滚动到的内容在layoutSubviews完成后实际上可能不可见。一个解决方案是控制器layoutIfNeeded在它知道这可能发生的情况下调用。

回答by CrazyPro007

The difference between these two methods can be now be described by referencing the update cycle.

现在可以通过引用更新周期来描述这两种方法之间的区别。

The method setNeedsLayout for a UIView tells the system that you want it to layout and redraw that view and all of its subviews, when it is time for the update cycle. This is an asynchronous activity, because the method completes and returns immediately, but it isn't until some later time that the layout and redraw actually happens, and you don't know when that update cycle will be.

UIView 的 setNeedsLayout 方法告诉系统您希望它在更新周期的时候布局和重绘该视图及其所有子视图。这是一个异步活动,因为该方法完成并立即返回,但直到稍后才真正发生布局和重绘,而且您不知道更新周期将在什么时候。

In contrast, the method layoutIfNeeded is a synchronous call that tells the system you want a layout and redraw of a view and its subviews, and you want it done immediately without waiting for the update cycle. When the call to this method is complete, the layout has already been adjusted and drawn based on all changes that had been noted prior to the method call.

相比之下,layoutIfNeeded 方法是一个同步调用,它告诉系统你想要一个视图及其子视图的布局和重绘,并且你希望它立即完成而无需等待更新周期。调用此方法完成后,布局已根据调用方法之前记录的所有更改进行了调整和绘制。

So, stated succinctly, layoutIfNeeded says update immediately please, whereas setNeedsLayout says please update but you can wait until the next update cycle.

所以,简而言之,layoutIfNeeded 表示请立即更新,而 setNeedsLayout 表示请更新,但您可以等到下一个更新周期。

回答by Avijit Nagare

LayoutSubViews() - Don't call directly, instead call setNeedsLayout(),override if constraint base not offer expected behaviour.

SetNeedsLayout()- Call on main thread, it wait for next drawing cycle. good for performance.

LayoutIfNeeded() - Layout subviews immediately.

LayoutSubViews() - 不要直接调用,而是调用 setNeedsLayout(),如果约束基础不提供预期行为,则覆盖。

SetNeedsLayout()- 调用主线程,等待下一个绘制周期。有利于性能。

LayoutIfNeeded() - 立即布局子视图。

回答by ennuikiller

setNeedsLayout actually calls layoutIfNeeded, so if your calling setNeedsDisplay there's no reason to call layoutIfNeeded. In this way setNeedsLayout is a convenience method for calling layoutIfNeeded which does the heavy lifting.

setNeedsLayout 实际上调用 layoutIfNeeded,因此如果您调用 setNeedsDisplay,则没有理由调用 layoutIfNeeded。通过这种方式, setNeedsLayout 是调用 layoutIfNeeded 的便捷方法,它可以完成繁重的工作。