awakeFromNib在iOS 9中未调用

时间:2015-09-25 19:11:56

标签: objective-c ios9 awakefromnib

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

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。)

2 个答案:

答案 0 :(得分:2)

iOS 9 Release Notes

中描述了对视图控制器笔尖加载行为的更改
  

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

     

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

此外,class documentation for UIViewController州:

  

如果为nibName参数指定nil并且未覆盖loadView方法,则视图控制器将按照nibName属性中的描述搜索nib文件。

如果您要在std::unique_ptr<char[]> buffer(new char[buffer_size]); getString(buffer.get(), buffer_size); std::string str(buffer.get()); 中执行初始化,则最好在-initWithNibNamed:bundle:和/或-initWithCoder:中执行此操作(取决于您正在执行的操作)。 -loadView仍适用于通常应该去的地方。

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

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

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

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

答案 1 :(得分:0)

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