【问题标题】:Why is my the designated initializer of UIViewController never called?为什么我的 UIViewController 的指定初始化程序从未被调用?
【发布时间】:2015-01-15 13:23:47
【问题描述】:

我使用基于视图的应用模板创建了一个新的 Xcode 项目。在视图控制器的 .m 中,我重写了这个:

// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        // Custom initialization

        NSLog(@"initWithNibName...");
    }
    return self;
}


- (id)init {
    NSLog(@"initWithNibName...");
    return [super init];
}

但是,我从来没有得到那个 NSLog。这也是我在其他项目中的经验。这个方法永远不会被调用。甚至没有来自 NSObject 的 -init。

视图控制器是在 XIB 文件中创建的。 Nib 加载系统如何在没有任何初始化的情况下实例化此类?

为什么?还有什么可以替代 -loadView 和 -viewDidLoad?

远离 XIB 文件的另一个重要原因?

【问题讨论】:

    标签: iphone ipad


    【解决方案1】:

    来自 iOS Resource Programming Guide

    在 iPhone OS 中,任何符合 NSCoding 协议的对象都使用initWithCoder: 方法进行初始化。这包括 UIViewUIViewController 的所有子类,无论它们是默认 Interface Builder 库的一部分还是您定义的自定义类。

    这样想:当你的视图控制器第一次在 Interface Builder 中创建时,会调用指定的初始化器。然后,当您保存 nib 文件时,视图控制器实例将存储在该文件中。稍后,当加载 nib 时,会从 nib 重新创建实例。

    由于它是重新创建而不是第一次创建,因此使用了不同的初始化方法。此方法 (-initWithCoder:) 使用 nib 文件中的值恢复对象的状态,其中可以包括指定初始化程序设置之外的属性设置。这种机制依赖于NSCoding 协议,这使得它可以通用地为许多不同的类工作。

    【讨论】:

    • 应该注意,如果您使用 nib 并通过直接调用 initWithNibName:bundle: 来实例化视图控制器,则会调用 initWithNibName:bundle:。只是现在你通常使用故事板,在这种情况下,它会调用 initWithCoder: 来代替。在故事板之前,我猜测默认的 Xcode 项目基于视图的应用程序模板没有调用 initWithNibName:bundle: 来实例化初始视图控制器。
    • @LironYahdav 如果你重新阅读这个问题,你会注意到它指出视图控制器是 in nib 文件,所以initWithNibName:bundle: 不可能是在加载 nib 时调用。
    【解决方案2】:

    您可以为此使用 - awakeFromNib。 仅当您在代码中这样做时才会调用 init。

    【讨论】:

    • 感谢您的提示!但是无论如何,Nib Loader 怎么会创建这个类的实例而不做任何初始化呢?
    • 从 NIB(或另一个 NSCoding 存档)加载的所有对象都使用 -initWithCoder: 进行初始化。
    • 是有道理的,但为什么 -init 从未被调用?它是 NSObject 的指定初始化器...
    • -awakeFromNib 不是初始化器,它属于视图控制器生命周期,可以多次调用(特别是在处理内存警告时;视图控制器可能会释放视图并稍后重建它们)。所以要小心你放在这里的东西。
    【解决方案3】:

    您是否将 MainWindow 的委托设置为您的 appDelegate..? 在您的 AppDelegate 和 applicationDidFinishLaunching Methode 中实施 UIApplicationDelegate,尝试 initWithNibName。 这样就可以了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-16
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-22
      • 1970-01-01
      • 2011-12-15
      相关资源
      最近更新 更多