我遇到了一个有趣的问题。我有一个视图控制器:
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
。)
答案 0 :(得分:2)
如果使用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
来解决这个问题。