为什么viewWillAppear没有被调用?

您为什么期望如此?

最有可能的是-您想知道您的用户将要看到一个屏幕。

有各种各样有用的理由想要这个。 也许您想跟踪分析屏幕视图,或触发数据获取以保持屏幕新鲜。 无论您的目标是什么,有人都可能告诉您检查viewWillAppear -好消息。 它会实现这些目标,但有时会起作用。 *

简单答案

调用viewWillAppear的技术原因很简单。

通知视图控制器其视图将被添加到视图层次结构中。

它不能是任何视图层次结构-它必须是在根目录下具有UIWindow视图层次结构(不一定是可见窗口)。

如果您从一个选项卡跳到另一个选项卡,或者从UINavigationController推送并弹出,那很好。 iOS正在从视图层次结构中删除视图,并每次都将其重新插入。 在所有这些过程中,视图仍保留在内存中,因此不会重复调用viewDidLoad

但是,当您开始在当前屏幕上显示视图时会遇到麻烦,因为有时*它将删除基础视图,但有时*不会。

展示您的View Controller

这完全取决于您如何呈现模态视图。 如果可能的话,iOS倾向于删除基础视图(内存很宝贵)。 但是,如果您的设计师坚持要保留该基本视图,则可以要求iOS通过设置正确的.modalPresentationStyle来保留它。

您可以选择以下选项,以及关闭后是否在其父视图上触发viewWillAppear

UIModalPresentationStyle选择

.none的文档说……

“不要使用这种样式来呈现视图控制器。”

他们通过崩溃强制执行此操作。 感谢Apple让我们保持警惕!

备用计划

当下面的视图保留时,关闭叠加视图时将不会调用viewWillAppear 。 要开展业务,您必须在dismiss呼叫中加入完成处理程序。

将引用传递给呈现的视图控制器的最佳方法是什么? 这确实取决于您如何设置应用程序,这超出了本文的范围。

缺失的环节

当我们将视图添加到窗口的视图层次结构时,iOS如何知道要通知哪个UIViewController ? 从UIViewController文档中,我们可以看到它具有对其拥有的view的引用,但是UIView文档中没有任何内容表明它知道哪个UIViewController拥有它。

这些present方法也没有什么特别的事情发生-即使直接添加视图, viewWillAppear调用也会发生。

仅仅因为苹果不告诉我们发生了什么,并不意味着我们就无法做出有根据的猜测。 让我们偷偷摸摸,检查专用API…

查看所有这些额外的属性! 而且只有一种具有我们要寻找的类型…… UIViewController* _viewDelegate;

让我们通过创建2个视图控制器进行测试。 我们将一个注入到另一个view_viewDelegate中,并将该view添加到窗口的视图层次结构中时,应调用注入的视图控制器的viewWillAppear

自己尝试一下!

警告 —请勿使用私有API交付应用程序。 这是一种危险的编码方式。 这些属性是私有的,Apple保留在不通知您的情况下随时更改其基础实现的权利。

Sean在 Livefront中度过 了自己最好的iOS生活

*有时 对软件开发人员来说是一个非常令人讨厌的词