我遇到了一个有趣的问题。我有一个视图控制器:
LoginViewController *viewController = [LoginViewController alloc] init];
在initWithNibName:bundle:
和awakeFromNib
方法中,我有一些初始化代码。LoginViewController有一个.xib文件,名为LoginViewController.xib.
然而,针对iOS 9构建,这些方法永远不会被调用,代码永远不会运行。但是,除非我像这样初始化我的LoginViewController
:
LoginViewController *viewController = [LoginViewController alloc] initWithNibName:nil bundle:nil];
然后运行代码,它工作得很好。看起来正在加载.xib文件,但是从未调用initWithNibName:bundle:
和awakeFromNib
。
有谁知道为什么在iOS 9 awakeFromNib
没有得到调用默认情况下,当相应的。xib存在?这个问题在iOS 8中不存在(即使我只是使用init
来初始化我的视图控制器,awakeFromNib
也会被调用)。
视图控制器nib加载行为的变化在iOS 9发布说明中有描述:
如果初始化为nil nibName值,UIViewController。nibName总是寻找一个与视图控制器类名称相似的nib,如果loadView没有被覆盖,nibName默认为那个值。在ios9之前,用Swift编写的UIViewController的子类会要求它们对应的nib文件名包含模块前缀。
为了提高重构时的灵活性,你可以在iOS 9中运行的代码中省略nib文件名中的模块名。ui。nibName仍然倾向于使用包含模块前缀的名称,但如果没有找到具有完全限定名称的nib,则会退回到非限定名称。
另外,UIViewController的类文档声明:
如果你为nibName参数指定nil,并且你没有覆盖loadView方法,视图控制器将按照nibName属性中的描述搜索nib文件。
如果你在-initWithNibNamed:bundle:
中执行初始化,最好在-initWithCoder:
和/或-loadView
中执行初始化(取决于你在做什么)。-awakeFromNib
仍然适用于通常应该放在那里的东西。
从你的问题看来,似乎:当视图控制器子类用-init
实例化时,-initWithNibNamed:bundle:
和awakeFromNib
不会被调用。- -initWithNibNamed:bundle:
和awakeFromNib
在视图控制器子类用-initWithNibNamed:bundle:
实例化时被调用。
这有点奇怪。-initWithNibNamed:bundle:
是指定的初始化器,因此-init
应该带nil参数调用它来触发上面描述的行为。使用Hopper在iOS 9上快速反汇编UIKit,可以看出情况仍然如此。
如果你覆盖-loadView
, -initWithNibName:bundle:
将不会尝试为你加载笔尖——通过覆盖-loadView
,你选择自己去做。如果你重写-loadView
(即使你调用super),删除它,nib应该加载。-awakeFromNib
不会被调用,因为视图控制器是nib的所有者-只有子节点会得到那个方法调用。如果它是故事板的一部分,它就会被调用。然而,-awakeAfterUsingCoder:
将被调用,并且可能是做您在-awakeFromNib
中尝试的工作的更好的地方。
我将你的问题简化为一个简单的测试用例,并在iOS 9和iOS 8.4 sdk中确认了这种行为。
我也遇到了同样的问题。由于某种原因,我的方法awakeFromNib -awakeFromNib
没有被调用。我知道这不是一个好的做法,但如果你关心你的代码,你可以使用NSNotificationCenter
来解决这个问题。