【发布时间】:2011-01-14 12:13:21
【问题描述】:
在创建视图控制器时应该什么时候使用init:,什么时候应该使用initWithNibName:bundle:?
【问题讨论】:
-
你应该改变这个问题的选择答案
标签: iphone objective-c uiviewcontroller initialization
在创建视图控制器时应该什么时候使用init:,什么时候应该使用initWithNibName:bundle:?
【问题讨论】:
标签: iphone objective-c uiviewcontroller initialization
如果您正在使用initWithNibName: bundle:...使用 nib 文件进行初始化!也就是说,您使用 Interface Builder 创建的文件。
如果您不使用 IB 来布局视图,则可以使用 init。
【讨论】:
-initWithNibName:bundle: 是 UIViewController 的指定初始化器。最终应该叫它。也就是说,尽管 Apple 的示例(在许多情况下倾向于简洁而不是可维护性),但绝不应该从视图控制器本身之外调用它。
你会经常看到这样的代码:
MYViewController *vc = [[MYViewController alloc] initWithNibName:@"Myview" bundle:nil];
我说这是不正确的。它将实现细节(NIB 的名称和甚至使用 NIB 的事实)放入调用者。这打破了封装。正确的做法是:
MYViewController *vc = [[MYViewController alloc] init];
然后,在 MYViewController 中:
- (instancetype)init
{
self = [super initWithNibName:@"Myview" bundle:nil];
if (self != nil)
{
// Further initialization if needed
}
return self;
}
- (instancetype)initWithNibName:(NSString *)nibName bundle:(NSBundle *)bundle
{
NSAssert(NO, @"Initialize with -init");
return nil;
}
这会将关键实现细节移回对象中,并防止调用者意外破坏封装。现在,如果您更改 NIB 的名称,或转向程序化构造,则将其修复在一个地方(在视图控制器中),而不是在使用视图控制器的每个地方。
【讨论】:
- (id)init { return [super initWithNibName:NSStringFromClass([self class]) bundle:nil]; }
nil 作为 nib 名称传递,它会根据视图控制器类计算出来。请参阅 UIViewController -nibName 的文档,该文档解释了它用于查找文件的启发式方法。
在没有 nib/xib 文件时使用 init,例如UI是通过编码创建的
使用 initWithNibName ,如果我们有一个 nib/xib 或同一个控制器共享超过 1 个 nib/xib
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[ViewController alloc] initWithNibName:@"ViewController_iPhone" bundle:nil];
} else {
self.viewController = [[ViewController alloc] initWithNibName:@"ViewController_iPad" bundle:nil];
}
我是这么想的。
【讨论】:
只要 xib 与视图控制器类同名,就可以调用 init。封装不是必需的。这样可以节省打字时间,但可能不够清晰。
NUDMainViewController *mainVC = [[NUDMainViewController alloc] init];
【讨论】: