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 方法,我可以只使用笔尖名称的前几个字符吗
viewDidLoad与initWithNibName的调用时机