【问题标题】:Why won't my awakeFromNib fire?为什么我的 awakeFromNib 不会触发?
【发布时间】:2010-12-08 00:15:54
【问题描述】:

我开始将更多的视图层次结构转移到 IB。

我有一个名为“AlignmentViewController.xib”的 nib 文件,我在其中设置了以 AlignmentViewController 作为文件所有者的视图层次结构。这很好用。

我仍然模糊不清的方法之一是 awakeFromNib。在 AlignmentViewController 的以下代码 sn-p 中,我添加了单个附加方法 awakeFromNib。但是,它不会被调用:

- (void)awakeFromNib {

   NSLog(@"AlignmentViewController - awakeFromNib");
   [super awakeFromNib];

}

- (id)initWithChromosomeName:(NSString *)chromosomeName 
               basepairStart:(NSUInteger)basepairStart 
                 basepairEnd:(NSUInteger)basepairEnd {

    self = [self initWithNibName:@"AlignmentViewController" bundle:nil];

    if (nil != self) {


        self.title          = @"Alignment";

        self.chromosomeName = chromosomeName;
        self.basepairStart  = basepairStart;
        self.basepairEnd    = basepairEnd;

        self.wantsFullScreenLayout = YES;

    }

    return self;
}

有人可以为我澄清一下我在这里错过了什么吗?

干杯, 道格

更新: 在阅读了一些答案后,我意识到我需要深入了解一些非常基本的东西。

看初始化:

- (id)initWithChromosomeName:(NSString *)chromosomeName 
               basepairStart:(NSUInteger)basepairStart 
                 basepairEnd:(NSUInteger)basepairEnd {

    self = [self initWithNibName:@"AlignmentViewController" bundle:nil];

我注意到我正在间接调用 initWithNibName:bundle:。这是不好的做法吗? AlignmentViewController.xib 文件定义了我的视图层次结构。但我并没有真正以典型的方式使用 initWithNibName:bundle: 吗?有没有更好的方法来做到这一点?

【问题讨论】:

  • FWIW,UIViewController 还提供了viewDidLoad,专门用于在视图加载后(无论是手动还是从 nib)在控制器中进行的任何处理。
  • 是的。我广泛使用 viewDidLoad。我只是想将更多的 UI 构造转移到 IB,我需要在某个时候处理 awakeFromNib。
  • 使用 IB 并不强制使用 awakeFromNib,也不与使用 viewDidLoad 相矛盾。

标签: iphone interface-builder nib xib


【解决方案1】:

-awakeFromNib 在所有 nib 对象实例化后发送到从 nib 实例化的所有对象。所有者不是这些对象之一。它在反序列化 nib 之前存在,并在加载后连接到 nib,因此不会发送-awakeFromNib(当然,除非它由其他一些 nib 本身实例化)。

这里的一个线索是不可能同时调用-initFromChromosomePair:basepairStart:basepairEnd:-awakeFromNib。 nib 加载器始终调用-initWithCoder:-initWithFrame:-init(发送的规则在Nib Object Life Cycle 中)。您有一些其他指定的初始化程序这一事实强烈表明您是在代码中的某处手动创建该对象,这意味着该对象不是“从 nib 中唤醒的”。

【讨论】:

  • 谢谢 Rob,我想我不清楚 initWithNibName:bundle: 的语义。在我的代码的其他地方,我确实调用了 initWithChromosomeName:basepairStart:basepairEnd: ,它又调用了 initWithNibName:bundle: ,如上所示。使用 initWithNibName:bundle: 时不会触发 nib 相关方法吗?
  • 多火;它们只是针对由 nib 加载器实例化的对象。笔尖的所有者不在笔尖,因此不会得到-awakeFromNib。 -viewDidLoad 被发送到视图控制器,这是您在 nib 完成加载后需要做的事情的地方。请注意,视图控制器可以在 nib 中,因此可以同时接收 -awakeFromNib (当它从父 nib 加载时)和稍后的 -viewDidLoad (当它自己的 nib 完成加载时)。 -awakeFromNib 在 nib 中的所有对象都已实例化并连接 IBOutlet 后发送到 nib 中的所有对象。
  • 现在我明白了。谢谢罗布,这真的很清楚。我忽略了这样一个事实,即 filesOwner 只是一个代理,而不是 nib 的成员。冷静。谢谢一百万个罗布。
  • 很好,当 Nib 的视图属于自定义类时,我没有意识到 FileOwner 不会收到此调用。
【解决方案2】:

只是添加一个说明:-awakeFromNib 发送给 Cocoa 中的文件所有者,而不是 Cocoa Touch。

From Apple's Docs:

...

  • 它将 awakeFromNib 消息发送到 nib 文件中定义匹配选择器的相应对象:
    • 在 Mac OS X 中,此消息被发送到定义该方法的任何接口对象。它还会发送给文件所有者以及定义它的任何代理对象。
    • 在 iPhone OS 中,此消息仅发送到由 nib 加载代码实例化的接口对象。它不会发送给文件所有者、第一响应者或任何其他代理对象。

【讨论】:

    【解决方案3】:

    根据您告诉我们的内容,我相信我知道您的问题是什么。 awakeFromNib 在从 nib 文件反序列化对象时调用。在这里,您有一个对象,即所有者,它存在于 笔尖加载之前。因此awakeFromNib 永远不会发送到您的AlignmentViewController.h

    如果您需要在此处执行某些操作,请尝试改用loadView。或者只是在加载笔尖后进行。在awakeFromNib 中你想做的事情是什么?

    【讨论】:

    • 谢谢戈登。只是试图更好地了解 nib 相关代码的语义和时序。我越来越依赖 IB 来构建 UI,但我仍然不确定 IB 世界和 XCode 世界是如何同步的。所以,nib 相关的方法不会触发我对 initWithNibName:bundle: 的使用吗?
    • 不,你的控制器上没有调用awakeFromNib,因为你的控制器不在笔尖中。它将在 nib 中的所有视图等上调用。
    • 请注意上面 Gordon 所说的“loadView”,我相信他的意思是“viewDidLoad”。在处理基于 nib 的视图控制器时,通常不应该使用 -loadView。
    • 十六和罗布,非常有帮助。雾正在消散。启蒙运动迫在眉睫。干杯。
    【解决方案4】:

    你应该重写 func awakeFromNib()。 不覆盖类 func awakeFromNib()

    override func awakeFromNib() {
        super.awakeFromNib()
        setupContent()
    }
    

    【讨论】:

      猜你喜欢
      • 2014-07-01
      • 1970-01-01
      • 2016-02-10
      • 2012-01-22
      • 1970-01-01
      • 1970-01-01
      • 2011-02-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多