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
How is layoutIfNeeded used?
提问by Boon
When and how is layoutIfNeeded
used? I know that when we change the layout of a view, we can call setNeedsLayout
to update the layout but not sure when layoutIfNeeded
should be used.
何时以及如何layoutIfNeeded
使用?我知道当我们改变视图的布局时,我们可以调用setNeedsLayout
来更新布局但不确定什么时候layoutIfNeeded
应该使用。
NOTE: I have layoutIfNeeded
used in actual code but forgot in what context it was used.
注意:我layoutIfNeeded
在实际代码中使用过,但忘记了它是在什么上下文中使用的。
回答by Allen Ding
layoutIfNeeded
forces 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 setNeedsLayout
when handling some user action). Then, your custom layoutSubviews
method 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 layoutIfNeeded
within a single run loop:
您可能需要layoutIfNeeded
在单个运行循环中调用的原因的示例:
- You resize a custom view containing a table view with a custom layout.
setNeedsLayout
is set so thatlayoutSubviews
will be called later. - A controller object asks the table view to scroll to some particular cell when handling a user event.
- Your custom view performs some custom sizing of the table view in
layoutSubviews
that changes the table view size.
- 您调整包含具有自定义布局的表格视图的自定义视图的大小。
setNeedsLayout
已设置,以便layoutSubviews
稍后调用。 - 控制器对象在处理用户事件时要求表格视图滚动到某个特定的单元格。
- 您的自定义视图对表格视图执行一些自定义大小调整,
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 layoutSubviews
is done. A solution then would be for the controller to call layoutIfNeeded
in 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 的便捷方法,它可以完成繁重的工作。