据我所知,awakeFromNib将始终在viewDidLoad之前调用。
所以我有一个UITableViewController的子类,它是从xib文件中取消归档的。
我在里面定义了这两个方法:
- (void)awakeFromNib {
[super awakeFromNib];
NSLog(@"awake from nib");
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"view did load");
}
会发生什么是“视图确实加载”出现在控制台中“从笔尖唤醒”之前。我试图在[超级awakeFromNib]上使用断点,并反复点击F7(Step Into),令我惊讶的是,它进入 - (void)viewDidLoad之前进入awakeFromNib内的第二行。
有谁知道这里发生了什么?我在常规UIViewController的子类中做了完全相同的事情,并且日志语句被反转,正如我最初预期的那样......
要了解这一事实,我建议你看看loadNibNamed:owner:options:
的NSBundle
方法。
从nib初始化视图控制器时,首先它会加载其中包含的视图,然后根据nib设置文件所有者属性。当viewDidLoad
方法将文件所有者的view
属性设置为其中一个已加载的视图时,将调用它。并且当设置所有文件所有者出口和属性(包括awakeFromNib
属性)时调用view
。因此,viewDidLoad
比awakeFromNib
更早被称为有意义。
希望这会有所帮助
我使用基于导航的应用程序选项创建测试项目,并将以下代码添加到rootViewController.m。
- (void)awakeFromNib {
NSLog(@"awakeFromNib 1");
[super awakeFromNib];
NSLog(@"awakeFromNib 2");
}
- (void)viewDidLoad {
NSLog(@"viewDidLoad 1");
[super viewDidLoad];
NSLog(@"viewDidLoad 2");
}
然后,我从控制台得到了结果:
awakeFromNib 1
awakeFromNib 2
viewDidLoad 1
viewDidLoad 2
加载控制器视图时将调用-(void)viewDidLoad
。因此,当您第一次使用self.view = ...
时,将调用-(void)viewDidLoad
。
如果你写了类似下面的内容,那么首先会调用-(void)viewDidLoad
。
- (void)awakeFromNib {
NSLog(@"awakeFromNib 1");
// The log sequence will be funny, if `viewDidLoad` raised before [super awakeFromNib]
// If you are curios about it, just give it a try.
// self.view.backgroundColor = [UIColor clearColor];
[super awakeFromNib];
/// viewDidLoad will be called
/// because self.view must be loaded first.
self.view.backgroundColor = [UIColor clearColor];
NSLog(@"awakeFromNib 2");
}
并获得以下结果。
awakeFromNib 1
viewDidLoad 1
viewDidLoad 2
awakeFromNib 2
如果成功加载视图,loadViewIfNeeded将触发viewDidLoad
。有时我会调用loadViewIfNeeded来确保@IBOutlet
实例被初始化,而不是null。
我不认为你必须在超类上调用awakeFromNib。
检查this。
编辑
我刚刚进行了快速测试,结果如下:
场景1:MainWindow.Xib有一个UIViewController子类TestingAwakeFromNibViewController
,它有自己的Nib文件TestingAwakeFromNibViewController.xib
。
TestingAwakeFromNibViewController有一个名为btn3的UIButton Outlet。测试以下代码:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"Btn3 %@",btn3);
NSLog(@"viewDidLoad");
}
-(void) awakeFromNib
{
[super awakeFromNib];
NSLog(@"Btn3 %@",btn3);
NSLog(@"awakeFromNib");
}
打印:
Btn3 (null)
AwakeFromNib
Btn3 <UIRoundedRectButton: 0x64088e0; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x6408890>>
ViewDidLoad
场景2:删除xib文件,将UIView作为子项添加到MainWindow.Xib内的TestingAwakeFromNibViewController,并将UIButton作为子视图添加到UIView(并将UI按钮插座连接到TestingAwakeFromNibViewController的相应插座)。
现在运行上面的代码将打印:
Btn3 <UIRoundedRectButton: 0x4e31c30; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e31be0>>
viewDidLoad
Btn3 <UIRoundedRectButton: 0x4e31c30; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e31be0>>
awakeFromNib
含义AwakeFromNib之前的ViewDidLoad。
第三种情景:与第二种情况相同,只是没有调用[super awakeFromNib];
Btn3 <UIRoundedRectButton: 0x4e0ddf0; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e0dda0>>
awakeFromNib
现在ViewDidLoad甚至没有被调用。
因此,似乎不同的场景要求采取不同的行动,我们需要根据我们所采取的行动做好准备。
在没有专家的情况下,并且在这篇帖子之后,我意识到比在Tab控制器场景中,在“子”视图控制器中,当加载选项卡控制器(父级)时执行awakeFromNib方法,但是只有当它的“选项卡”是“Tab”时才执行viewDidLoad点击。
因此,据我所知,只有在选择了特定选项卡(点击)时,才可以使用此功能加载数据