viewDidLoad和awakeFromNib时序

bog*_*don 10 iphone uitableview viewdidload ipad awakefromnib

据我所知,awakeFromNib将始终在viewDidLoad之前调用.

所以我有一个UITableViewController的子类,它是从xib文件中取消归档的.

我在里面定义了这两个方法:

- (void)awakeFromNib {
  [super awakeFromNib];
  NSLog(@"awake from nib");
}

- (void)viewDidLoad {
  [super viewDidLoad];
  NSLog(@"view did load");
}
Run Code Online (Sandbox Code Playgroud)

会发生什么是"视图确实加载"出现在控制台中"从笔尖唤醒"之前.我试图在[超级awakeFromNib]上使用断点,并反复点击F7(Step Into),令我惊讶的是,它进入 - (void)viewDidLoad之前进入awakeFromNib内的第二行.

有谁知道这里发生了什么?我在常规UIViewController的子类中做了完全相同的事情,并且日志语句被反转,正如我最初期望的那样......

Zap*_*pko 12

要了解这个事实,我建议你看看loadNibNamed:owner:options: 方法NSBundle.

从nib初始化视图控制器时,首先它会加载其中包含的视图,然后根据nib 设置文件所有者属性.viewDidLoad当将文件所有者的view属性设置为其中一个已加载的视图时,将调用该方法.并且awakeFromNib在设置所有文件所有者出口和属性(包括view属性)时调用.因此,有必要viewDidLoad提前调用awakeFromNib.

希望这会有所帮助

  • 我不确定你是对的.看看这个:http://stackoverflow.com/questions/377202/which-should-i-use-awakefromnib-or-viewdidload (2认同)

Aec*_*Liu 6

我使用基于导航的应用程序选项创建一个测试项目,并将以下代码添加到rootViewController.m。

- (void)awakeFromNib {
     NSLog(@"awakeFromNib 1");
     [super awakeFromNib];
     NSLog(@"awakeFromNib 2");
}

- (void)viewDidLoad {
     NSLog(@"viewDidLoad 1");
     [super viewDidLoad];
     NSLog(@"viewDidLoad 2");
}
Run Code Online (Sandbox Code Playgroud)

然后,我从控制台获得了结果:

awakeFromNib 1
awakeFromNib 2
viewDidLoad 1
viewDidLoad 2
Run Code Online (Sandbox Code Playgroud)

-(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");
  }
Run Code Online (Sandbox Code Playgroud)

并获得以下结果。

awakeFromNib 1
viewDidLoad 1
viewDidLoad 2
awakeFromNib 2
Run Code Online (Sandbox Code Playgroud)

更新资料

viewDidLoad如果成功加载视图,则将触发loadViewIfNeeded。有时我会调用loadViewIfNeeded以确保@IBOutlet实例已初始化,并且不再为null。


Ida*_*dan 5

我不认为你必须在超类上调用awakeFromNib.

检查一下.

编辑

我刚刚进行了快速测试,结果如下:

场景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");
}
Run Code Online (Sandbox Code Playgroud)

打印:

Btn3 (null)
AwakeFromNib
Btn3 <UIRoundedRectButton: 0x64088e0; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x6408890>>
ViewDidLoad
Run Code Online (Sandbox Code Playgroud)

场景2: 删除xib文件,将UIView作为子项添加到MainWindow.Xib内的TestingAwakeFromNibViewController,并将UIButton作为子视图添加到UIView(并将UIbutton插座连接到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
Run Code Online (Sandbox Code Playgroud)

含义AwakeFromNib之前的ViewDidLoad.

第三种情景:与第二种情况相同,只是没有打电话[super awakeFromNib];

Btn3 <UIRoundedRectButton: 0x4e0ddf0; frame = (114 211; 72 37); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x4e0dda0>>
awakeFromNib
Run Code Online (Sandbox Code Playgroud)

现在ViewDidLoad甚至没有被调用.

因此,似乎不同的场景要求采取不同的行动,我们需要根据我们所采取的行动做好准备.