使用 UINavigationController 弹出顶视图时不再调用 viewDidLayoutSubviews

viewDidLayoutSubviews no longer called when popping top view with UINavigationController

iOS10、不断断掉的礼物,好像又换了一个行为。

假设两个 UIViewController 被推送到一个 UINavigationController 上。

在 iOS 8 月 9 日,调用 navigationController?.popViewController(animated: true) 弹出顶部 UIViewController(比如 VC2)导致底部视图控制器(比如 VC1)上的 viewDidLayoutSubviews 被调用。

我们就是靠这个来刷新VC1的。有时 VC2 会向 VC1 添加子视图(通过数据模型),这需要在弹出回 VC1 时得到反映。

需要准确的帧信息。我们不能使用 viewWillAppear 因为 viewDidAppear 的问题是在最初看到视图和调整之间存在短暂的故障。

现在弹出 VC2 时不会调用 VC1 的 viewDidLayoutSubviews

1) 这是 viewDidLayoutSubviews 无法调用的错误吗?

2) 使用 UINavigationController 弹出时刷新视图控制器的正确方法是什么?

依赖viewDidLayoutSubviews从来都不是正确的解决方案。 UIViewController 提供 viewWillAppear:viewDidAppear: 用于此类用途。当 VC2 从导航控制器中弹出时,将在 VC1 上调用这两个方法,让您知道它将会或现在再次可见。

viewDidLayoutSubviews 只能用于调整视图框架和布局。

viewWill|DidAppear: 应用于处理视图控制器最初或再次可见。在您的情况下,您应该使用它来根据需要更新数据和 add/update 视图。这些新视图应该基于视图控制器的当前框架来设置。它们将根据需要在您实施 viewDidLayoutSubviews 时进行调整。

我会补充rmaddy的回答。您需要分离执行布局和更新数据。如果您的流程是在视图即将出现时更新数据,您应该在 viewWillAppear: 中更新控制器的视图支持数据,重新加载视图,然后使用 setNeedsLayout 将视图标记为需要布局.这将导致系统在控制器的视图上执行布局,并将触发布局。这样,您可以确保在视图准备就绪后执行布局,而不是之前(在 viewWillAppear:.

中经常出现这种情况)