ChatGPT解决这个技术问题 Extra ChatGPT

什么时候调用 layoutSubviews?

我有一个自定义视图在动画期间没有收到 layoutSubview 消息。

我有一个充满屏幕的视图。如果我更改导航栏的高度,它在屏幕底部有一个自定义子视图,可以在 Interface Builder 中正确调整大小。 layoutSubviews 在创建视图时调用,但不再调用。我的子视图布局正确。如果我关闭通话状态栏,则根本不会调用子视图的 layoutSubviews,即使主视图确实为其调整大小设置了动画。

在什么情况下实际调用了 layoutSubviews

我将自定义视图的 autoresizesSubviews 设置为 NO。在 Interface Builder 中,我设置了顶部和底部支柱以及垂直箭头。

难题的另一部分是必须将窗口设为关键:

[window makeKeyAndVisible];

否则子视图不会自动调整大小。


D
Derek Lee

我有一个类似的问题,但对答案(或我能在网上找到的任何答案)不满意,所以我在实践中尝试过,这就是我得到的:

init 不会导致 layoutSubviews 被调用(duh)

addSubview:导致 layoutSubviews 在被添加的视图、被添加到的视图(目标视图)以及目标的所有子视图上调用

视图 setFrame 仅在框架的大小参数不同时智能地调用已设置其框架的视图上的 layoutSubviews

滚动 UIScrollView 会导致在 scrollView 及其父视图上调用 layoutSubviews

旋转设备仅在父视图(响应的 viewControllers 主视图)上调用 layoutSubview

调整视图的大小将在其父视图上调用 layoutSubviews (重要:如果确定其大小的内容发生更改,则具有内在内容大小的视图将重新调整大小;例如,更新 UILabel 上的文本将导致更新内在内容大小和因此在其父视图上调用 layoutSubviews)

我的结果 - http://blog.logichigh.com/2011/03/16/when-does-layoutsubviews-get-called/


很好的答案。我一直想知道layoutSubviewsinitWithFrame: 会导致 layoutSubviews 被调用吗?
@Robert - 我使用的是 initWithFrame ......所以没有。
@BadPirate:是的。根据我的实验,如果您调整 view1.1 的大小,它会调用 view1layoutSubviews,然后调用 view1.1layoutSubviews。此调用不会无限期地传播到超级视图,在 view1.1.1 上调用它只会在 view1.1view1.1.1 上调用 layoutSubviews。只是移动而不改变它的大小不会对它们中的任何一个调用 layoutSubviews
在 UIView(但 UIViewController)上不调用 viewDidLoad。在 UIView 被初始化后,视图是否加载被调用。
根据我的实验,第二条规则可能不准确:当我将 view1.2 添加到 view1 时,会调用 view1.2view1layoutSubviews,但不会调用 view1.1layoutSubviews。 (view1.1view1.2view1 的子视图)。 也就是说,并不是目标视图的所有子视图都调用了layoutSubviews方法
P
Patrick Pijnappel

在@BadPirate 之前的回答的基础上,我做了一些进一步的实验,并提出了一些澄清/更正。我发现当且仅当以下情况下才会在视图上调用 layoutSubviews:

它自己的界限(不是框架)发生了变化。

它的直接子视图之一的边界发生了变化。

子视图被添加到视图中或从视图中删除。

一些相关细节:

仅当新值不同(包括不同的原点)时,才认为边界已更改。请特别注意,这就是为什么 layoutSubviews: 在 UIScrollView 滚动时调用的原因,因为它通过更改其边界的原点来执行滚动。

更改框架只会在大小发生更改时更改边界,因为这是传播到边界属性的唯一内容。

尚未在视图层次结构中的视图边界的更改将导致对 layoutSubviews 的调用:当视图最终添加到视图层次结构中时。

并且只是为了完整性:这些触发器不直接调用 layoutSubviews,而是调用 setNeedsLayout,它设置/引发一个标志。运行循环的每次迭代,对于视图层次结构中的所有视图,都会检查此标志。对于发现标志的每个视图,都会调用 layoutSubviews: 并重置标志。层次较高的视图将首先被检查/调用。


不能足够支持这个答案。它应该是最佳答案。给出的三个规则就是你所需要的。我从来没有遇到过这些规则没有完美描述的任何 layoutSubview 行为。
我不认为 layoutSubviews 在直接子视图的边界发生更改时被调用。我认为 layoutSubviews 的调用只是您测试的副作用。在某些情况下,当子视图边界发生变化时,不会调用 layoutSubviews。请检查 frogcjn 的答案,因为他的 anwser 是基于 Apple 的文档,而不仅仅是实验。
j
jscs

https://developer.apple.com/library/prerelease/tvos/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html#//apple_ref/doc/uid/TP40009503-CH5-SW1

每当视图中发生以下任何事件时,都可能发生布局更改:视图边界矩形的大小发生变化。湾。发生界面方向更改,这通常会触发根视图的边界矩形的更改。 C。与视图层关联的一组核心动画子层发生变化并需要布局。 d。您的应用程序通过调用视图的 setNeedsLayout 或 layoutIfNeeded 方法来强制进行布局。 e.您的应用程序通过调用视图底层对象的 setNeedsLayout 方法来强制布局。

https://i.stack.imgur.com/4LSv0.png


此外,需要指出的重要一点是,当视图尚未添加到视图堆栈时,不会调用这些事件。您将其与“can”一词一起包含在内,但具体而言,当其中一个事件将其标记为需要布局时,它将在应用程序主线程的下一个可用周期中调用。
C
Community

BadPirate's answer 中的一些观点只是部分正确:

对于 addSubView 点 addSubview 导致 layoutSubviews 在被添加的视图、它被添加到的视图(目标视图)以及目标的所有子视图上被调用。它取决于视图的(目标视图)自动调整大小掩码。如果它启用了自动调整掩码,layoutSubview 将在每个 addSubview 上调用。如果它没有自动调整大小掩码,则仅当视图的(目标视图)帧大小更改时才会调用 layoutSubview。示例:如果您以编程方式创建了 UIView(默认情况下它没有自动调整大小掩码),则仅当 UIView 框架更改而不是在每个 addSubview 上时才会调用 LayoutSubview。正是通过这种技术,应用程序的性能也得到了提高。对于设备旋转点 旋转设备仅调用父视图(响应 viewController 的主视图)上的 layoutSubview 仅当您的 VC 位于 VC 层次结构中(window.rootViewController 的根目录)时才会如此,这是最常见的情况。在 iOS 5 中,如果你创建了一个 VC,但它没有被添加到任何另一个 VC 中,那么当设备旋转时,这个 VC 不会被注意到。因此,调用 layoutSubviews 不会注意到它的视图。


S
Steve Weller

我将解决方案追溯到 Interface Builder 坚持认为在打开了模拟屏幕元素(状态栏等)的视图上不能更改弹簧。由于主视图的弹簧已关闭,因此该视图无法更改大小,因此在出现通话栏时会完全向下滚动。

关闭模拟功能,然后调整视图大小并正确设置弹簧会导致动画发生并调用我的方法。

调试中的一个额外问题是,当通过菜单切换通话状态时,模拟器会退出应用程序。退出应用程序 = 没有调试器。


您是说在调整视图大小时调用 layoutSubviews 吗?我一直以为不是...
这是。当视图被调整大小时,它需要对其子视图做一些事情。如果您不提供它,那么它会使用弹簧、支柱等自动移动它们。
b
bademi

在 viewController 中调用 [self.view setNeedsLayout]; 使其调用 viewDidLayoutSubviews


W
Willi Ballenthin

你看过layoutIfNeeded吗?

文档片段如下。如果在动画期间显式调用此方法,动画是否有效?

layoutIfNeeded 如果需要,布局子视图。

- (void)layoutIfNeeded

讨论 使用此方法在绘制之前强制子视图的布局。

可用性 适用于 iPhone OS 2.0 及更高版本。


T
Tal Yaniv

将 OpenGL 应用程序从 SDK 3 迁移到 4 时,不再调用 layoutSubviews。经过大量试验和错误后,我终于打开了 MainWindow.xib,选择了 Window 对象,在检查器中选择了 Window Attributes 选项卡(最左侧)并选中了“Visible at launch”。似乎在 SDK 3 中它仍然会导致 layoutSubViews 调用,但在 4 中没有。

6小时的挫败感告一段落。


你做了窗户钥匙吗?如果没有,这可能会导致各种有趣的事情不会发生。

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅