initWithNibName 是如何工作的?

Posted

技术标签:

【中文标题】initWithNibName 是如何工作的?【英文标题】:How does initWithNibName work? 【发布时间】:2012-10-15 18:50:07 【问题描述】:

我过去常常以编程方式创建我的视图,并开始使用 XIB 文件进行切换。我找到了这段代码:

-(id)init

    self = [super initWithNibName:@"HelpViewController"  bundle:nil];
    if (self != nil) 
        // further initialization needed
    

    return self;


-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    NSAssert(NO, @"Initialize with -init");
    return nil;

它有效,但为什么呢?如果我遵循逻辑,initWithNibName 返回 nil 并将其设置为 self。所以,self 现在是 nil,然后你在 init 结束时返回 self。嗯,这意味着你返回 self ,它是 nil 。对吗?

另外,如果我想初始化一个 NSArray,我应该把它放在那个 init 函数的什么地方?

谢谢你的解释。

Yko

【问题讨论】:

在您的 sn-p 中,如果您调用 initWithNibName:bundle:,则不会初始化任何内容。您应该改为调用init 并进一步初始化其中的对象。这个 pattern 试图 enforce proper encapsulation 并向调用者隐藏 nib 名称,因为它是一个实现细节。 我假设这是自动生成的代码?如果是这样,它基本上是告诉你调用 init 来初始化它,它会在 init 函数内部自行处理 initWithNibName:bundle: 。它基本上只是让你少打字,让事情变得更容易。 没有。这是很好的自动生成代码。它实际上是我在 SO 中找到的代码,重点是封装,因此我可以调用 [ClassName alloc] init] 而不是在类之外指定实际的 Nib 名称。这就说得通了。遵循代码不会。我发现一个更有意义的是 initWithNibName 返回 [self init] 而不是 nil。我只是不明白那个零。 【参考方案1】:

因为 init 方法调用了 self = [super initWithNibName...]。所以你必须调用init方法来创建对象。如果你使用 initWithNibName 它会失败

对于数组,你应该在 init 方法中初始化

-(id)init

    self = [super initWithNibName:@"HelpViewController"  bundle:nil];
    if (self != nil) 
        // further initialization needed
        myArray = [[NSMutableArray alloc] init];
    

    return self;

【讨论】:

这完全正确。它调用超类中的函数,应该是UIViewController。该功能不可编辑(好吧,您不应该对其进行编辑),因此请相信它正在执行您想要的操作。 (PS - 这只是对 OP 的进一步评论) 我试图理解 return nil 部分。我不明白。我找到了另一个更有意义的。在 initWithNibName 中,它返回 [self init] 而不是 nil。好吧,实际上这也没有任何意义,因为 [self init] 调用了 initWithNibName... 我想我混淆了超类和 UIViewController 类。这就是我想了解的。【参考方案2】:

您正在查看两个不同的 initWithNibName 函数。

-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    NSAssert(NO, @"Initialize with -init");
    return nil;

上述函数覆盖了 initWithNibName 的超类版本。它引发一个断言,通知调用者使用 init。

self = [super initWithNibName:@"HelpViewController"  bundle:nil];

上面一行调用了initWithNibName的超类版本,它返回一个视图控制器。

如果你想初始化一个数组,你可以在“需要进一步初始化”注释的地方初始化它。

【讨论】:

是的。我想我混淆了超类和 UIVIewController 类。这就是我想了解的地方。假设我分配并初始化视图控制器,它会进入 init,调用超级 initWithNibName,但这与实现文件中指定的 initWithNibName 不同,对吧?还是因为我覆盖了它?那为什么它返回零呢?那部分令人困惑 @Yko 不是同一个initWithNibName,它是在超类中实现的,因为你在super上调用它,而不是self。【参考方案3】:

之所以有效,是因为您在 super(很可能是 UIViewController)而不是 self(您的 UIViewController 的子类)上调用 -initWithNibName:bundle:。如果您要在 self 上调用 initWithNibName:bundle,那么如果您禁用了断言,您将点击断言或返回 nil。 -initWithNibName:bundle: 的超类实现不受您的实现影响,因此继续正常运行。

【讨论】:

以上是关于initWithNibName 是如何工作的?的主要内容,如果未能解决你的问题,请参考以下文章

initWithNibName 调用了两次或加载了错误的 xib

卡在 initWithNibName

initWithNibName 方法,我可以只使用笔尖名称的前几个字符吗

viewDidLoad与initWithNibName的调用时机

iOS - 为啥在 initWithNibName 中设置和显示子视图不起作用?

initWithNibName、awakeFromNib 和 viewDidLoad 的描述?