iOS 9 中未调用 awakeFromNib

Posted

技术标签:

【中文标题】iOS 9 中未调用 awakeFromNib【英文标题】:awakeFromNib Not Called in iOS 9 【发布时间】:2015-09-25 19:11:56 【问题描述】:

我遇到了一个有趣的问题。我有一个视图控制器:

LoginViewController *viewController = [LoginViewController alloc] init];

initWithNibName:bundle:awakeFromNib 方法中,我有一些初始化代码。 LoginViewController 有一个名为 LoginViewController.xib 的 .xib 文件。

但是,针对 ios 9 构建,这些方法永远不会被调用,代码也永远不会运行。但是,除非我像这样初始化我的LoginViewController

LoginViewController *viewController = [LoginViewController alloc] initWithNibName:nil bundle:nil];

然后代码运行,它工作得非常好。似乎正在加载 .xib 文件,但从未调用过 initWithNibName:bundle:awakeFromNib

有谁知道为什么在 iOS 9 中 awakeFromNib 在存在相应的 .xib 时默认不会被调用?这个问题在 iOS 8 中不存在(awakeFromNib 被调用,即使我只是使用init 来初始化我的视图控制器)。

【问题讨论】:

嗯,这对我来说是合乎逻辑的。没有NIB,所以它不会调用awakeFromNib @FreeNickname 抱歉,我忘了说 LoginViewController 确实有一个 .xib 文件。我已经编辑了问题以反映这一点。 xib叫什么? @Fogmeister .xib 同名 LoginViewController (LoginViewController.xib)。 好吧,你将不得不提供更多的代码或其他东西。您说它与 initWithNibNamed 一起使用...但是您提供的 nib 名称是 nil。这将迫使它不使用笔尖。所以如果你使用它,awakeFromNjb 绝对不应该工作。能不能再解释一下。 init 和 awakeFromNib 中的哪一个在工作/不工作,什么时候工作? 【参考方案1】:

iOS 9 Release Notes 中描述了对视图控制器 nib 加载行为的更改:

如果用 nil nibName 值初始化,UIViewController.nibName 总是寻找与视图控制器的类具有相似名称的 nib,如果 loadView 没有被覆盖,则默认为该值。 在 iOS 9 之前,用 Swift 编写的 UIViewController 的子类需要它们对应的 nib 文件名包含模块前缀。

为了提高重构时的灵活性,您可以在 iOS 9 中运行的代码中从 nib 文件名中省略模块名称。 UIViewController.nibName 仍然更喜欢包含模块前缀的名称,但回退到不合格的名称如果未找到具有完全限定名称的 nib。

另外,class documentation for UIViewController 声明:

如果您为 nibName 参数指定 nil 并且不覆盖 loadView 方法,则视图控制器会按照 nibName 属性中的说明搜索 nib 文件。

如果您在-initWithNibNamed:bundle: 中执行初始化,最好在-initWithCoder: 和/或-loadView 中执行初始化(取决于您在做什么)。 -awakeFromNib 仍然适用于通常应该去那里的东西。

从您的问题看来: - 当使用-init 实例化视图控制器子类时,不会调用-initWithNibNamed:bundle:awakeFromNib。 - -initWithNibNamed:bundle:awakeFromNib 正在 当视图控制器子类被 -initWithNibNamed:bundle: 实例化时被调用。

这有点奇怪。 -initWithNibNamed:bundle: 是指定的初始化程序,因此 -init 应该使用 nil 参数调用它以触发上述行为。在 iOS 9 上使用Hopper 快速反汇编 UIKit 表明情况仍然如此。

如果您覆盖 -loadView -initWithNibName:bundle: 将不会尝试为您加载笔尖 - 通过覆盖 -loadView 您选择自己这样做。如果您要覆盖 -loadView(即使您调用 super),请将其删除,笔尖应该会加载。 -awakeFromNib 不会被调用,因为视图控制器是 nib 的所有者 - 只有孩子才能获得该方法调用。如果它是情节提要的一部分,它将被调用。但是,-awakeAfterUsingCoder: 将被调用,并且可能是一个更好的地方来完成您在 -awakeFromNib 中尝试的工作。

我将您的问题简化为一个简单的测试用例,并在 iOS 9 和 iOS 8.4 SDK 上确认了这种行为。

【讨论】:

【参考方案2】:

我遇到了同样的问题。出于某种原因,我的方法 awakeFromNib -awakeFromNib没有被调用。我知道这不是一个好习惯,但如果您注意自己的代码,您可以使用NSNotificationCenter 来解决这个问题。

【讨论】:

以上是关于iOS 9 中未调用 awakeFromNib的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 9 中未调用 updateSearchResultsForSearchController

在 iOS 11 和 Xcode 9.1 中未调用 CLLocationManager 的 didUpdateLocations 委托 [重复]

“viewWillTransitionToSize:”当视图控制器以模态方式呈现时在 iOS 9 中未调用

准备(用于 segue:UIStoryboardSegue,发件人:任何?)在 iOS 11 上的 Xcode 9 b6 中未调用

在 iOS 15 中未分配 Alamofire 4.9.1 sessionManager.delegate.sessionDidReceiveChallenge

推送通知在 ios 9 中未显示 2kb