initWithNibName,awakeFromNib和viewDidLoad的描述?

时间:2009-08-06 16:23:50

标签: iphone ios cocoa-touch

是否对initWithNibNameawakeFromNibviewDidLoad有一个很好的概述,列出了使用这些内容的最佳方法,并准确描述了每种方法的作用?我发现这些非常令人困惑。在使用View Controller生成的模板中,有关initWithNibName的评论说:

  

指定的初始化程序。覆盖以执行加载视图之前所需的设置。

除了似乎永远不会调用此方法(我正在使用IB来设置View Controller)。那么我应该使用awakeFromNibviewDidLoad进行初始化吗?

3 个答案:

答案 0 :(得分:35)

我刚刚完成了对这个主题的一些研究,所以我想我会分享一些我学到的东西。

  1. awakeFromNib用于iPhone的视图没有任何问题。请参阅this Apple Dev document

  2. initWithCoder 是从NIB文件加载视图时进行初始化的好地方,因为同一NIB文件中的其他项可能已初始化,也可能未初始化在那时候。例如,出口可能仍然是零。 相同的NIB文件中的所有项目都可以在调用awakeFromNib时正确初始化。

  3. viewDidLoad 在viewController中进行设置工作的好地方。

  4. 那么为什么要在视图中使用awakeFromNib呢?我能想到的一个原因是,如果在初始化视图并将其连接到NIB文件中的其他对象之后,您想要执行某些操作,但是您希望仅将其封装在视图中。这减少了与视图控制器的链接。

答案 1 :(得分:24)

如果您要在IB中创建视图,则应使用viewDidLoad。每次初始化视图时都会调用它。您使用initWithNibName:在代码中创建视图时。您不应该将awakeFromNib与iPhone的视图一起使用。

initWithNibName似乎没有被调用的原因是接口构建器实际上创建了一个视图控制器的实例,然后序列化该视图。因此,当您在IB中创建视图控制器(基本上将其添加到项目中)时,IB会调用initWithNibName,但除非您已覆盖默认的encodeWithCoder:,否则您设置的任何瞬态变量从nib(反序列化)加载视图时将会消失。这通常是可以的,因为您通常希望使用特定于应用程序当前,运行上下文的信息来设置视图,而不是预先确定的初始化程序。

但是,即使您以编程方式创建视图和视图控制器,仍然可以将所有初始化放在viewDidLoad中。这通常更好,因为如果您的视图最终被缓存(卸载)然后又返回到屏幕上,则可以再次调用viewDidLoad,而初始化程序不一定。例如,您以编程方式创建视图并将其推送到导航控制器的堆栈 - 稍后视图已被掩盖并发出内存警告,以便导航控制器“卸载”您的视图但不释放对象 - 当视图时回来(其他视图弹出),导航控制器将再次调用viewDidLoad,以便您可以重新初始化,但不会再次调用initWithNib。请注意,这是一种罕见的情况,但无论如何,大多数人的应用程序会因其他原因而死亡。

答案 2 :(得分:0)

viewDidLoad可以不止一次被调用,因此它不适合大多数初始化(虽然在实践中它只被调用一次,除非你干涉) - 这就是为什么awakeFromNib特殊而且非常必要:它只是被召唤一次。

viewDidLoad在UIView上不存在 - UIView有awakeFromNib进行初始化,没有其他合理的选项。

在过去的六个月里,我一直很高兴地将awakeFromNib与故事板(应用程序的单个故事板)一起使用,完全没有任何问题,并且它与所有按照文档中指定的配置进行了完美配合。然后今天我把一些代码拆开并放入一个新的视图控制器和视图,并且没有一个像我过去经历过的那样工作,即所有出口都在awakeFromNib中。我的理论很简单 - SDK很糟糕,因为它很容易在你的控制器/视图和类链中的某个地方做一些微不足道的事情并打破一切。

现在我开始研究这个毫无意义的话题,但是,当我需要的只是一个简单的一致的地方进行初始化时。