10

我的理解是 awakeFromNib 总是在 viewDidLoad 之前被调用。

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

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

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

- (void)viewDidLoad {
  [super viewDidLoad];
  NSLog(@"view did load");
}

发生的事情是在控制台中的“从笔尖唤醒”之前显示“视图确实加载”。我尝试在 [super awakeFromNib] 处使用断点,并反复按 F7(Step Into),令我惊讶的是,它在进入 awakeFromNib 内的第二行之前进入了 -(void)viewDidLoad。

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

4

4 回答 4

12

要了解这一事实,我建议您查看loadNibNamed:owner:options: .NSBundle

当您从 nib 初始化视图控制器时,首先它会加载其中包含的视图,然后根据 nib设置文件所有者属性。viewDidLoad方法在将文件所有者的view属性设置为已加载的视图之一时被调用。并且awakeFromNib在设置所有文件所有者的出口和属性(包括view属性)时调用。viewDidLoad因此,早于 调用是有道理的awakeFromNib

希望这会有所帮助

于 2011-06-10T07:56:44.710 回答
6

我使用基于导航的应用程序选项创建了一个测试项目,并将以下代码添加到 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

更新

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

于 2011-06-10T10:54:26.703 回答
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");
}

将打印:

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(并将 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

意思是 ViewDidLoad 在 AwakeFromNib 之前。

第三个场景:和第二个一样,只是没有调用[super awakeFromNib];

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

现在 ViewDidLoad 甚至没有被调用。

所以,似乎不同的场景需要不同的行动,我们需要根据我们正在采取的行动做好准备。

于 2011-06-10T07:54:41.303 回答
1

在没有专家,并且在此帖子之后,我意识到除了在“子”视图控制器中,在“子”视图控制器中,当加载选项卡控制器(父级)时,执行了avakefromnib方法,但仅在其“选项卡”时查看viewDidLoad点击。

而且,因此我知道只有在选择(单击)特定选项卡时才能使用它来加载数据

于 2013-04-03T11:48:33.543 回答