【问题标题】:viewDidLoad and awakeFromNib timingviewDidLoad 和 awakeFromNib 计时
【发布时间】:2011-09-12 06:10:16
【问题描述】:

据我了解,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 的子类中做了完全相同的事情,并且日志语句被颠倒了,正如我最初预期的那样......

【问题讨论】:

    标签: iphone ipad uitableview viewdidload awakefromnib


    【解决方案1】:

    我认为你不必在你的超级类上调用 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(并将 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 甚至都没有被调用。

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

    【讨论】:

    • 有趣。如果不调用 [super awakeFromNib],则根本不调用 viewDidLoad。所以一直以来,[super awakeFromNib] 调用 viewDidload?
    【解决方案2】:

    要了解这个事实,我建议您查看NSBundleloadNibNamed:owner:options: 方法。

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

    希望这会有所帮助

    【讨论】:

    • 我不确定你是对的。看看这个:stackoverflow.com/questions/377202/…
    • 那么与我所说的冲突在哪里?事实是,当内存警告发生时,视图控制器视图(如果它不可见)被设置为 nil 并被释放。当它再次可见时,视图控制器从其 xib 文件加载其视图并设置self.view = viewLoadedFromXib,因此再次调用 viewDidLoad 而它不会再次配置自身不会再次调用 awakeFromNib。
    • 如果你不相信我或者我写的不是很清楚,你可以自己查看documentation。无论如何,它会更有用。
    • 你专注于错误的事情,内存警告不是我想让你看到的。无论如何,请参阅我编辑的答案。
    • @Zapko 非常感谢,非常感谢。任何论坛都没有围绕这一点进行讨论。此外,尽管是一个有效的问题,但我的问题在 SO 上却被吹倒了。
    【解决方案3】:

    我创建了一个带有 Navigation-based Application 选项的测试项目,并将以下代码添加到 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 实例已初始化,并且不再为空。

    【讨论】:

      【解决方案4】:

      而不是专家,并在此帖子之后,我意识到除了在“子”视图控制器中的选项卡控制器方案中,当加载Tab Controller(父级)时,执行AwakeFromNib方法,但仅在其“viewDidload时”选项卡”被点击。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-22
        • 2013-03-16
        • 1970-01-01
        相关资源
        最近更新 更多