【问题标题】:When should I initialize a view controller using initWithNibName?何时应该使用 initWithNibName 初始化视图控制器?
【发布时间】:2011-01-14 12:13:21
【问题描述】:

在创建视图控制器时应该什么时候使用init:,什么时候应该使用initWithNibName:bundle:

【问题讨论】:

  • 你应该改变这个问题的选择答案

标签: iphone objective-c uiviewcontroller initialization


【解决方案1】:

如果您正在使用initWithNibName: bundle:...使用 nib 文件进行初始化!也就是说,您使用 Interface Builder 创建的文件。

如果您不使用 IB 来布局视图,则可以使用 init

【讨论】:

    【解决方案2】:

    -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 的名称,或转向程序化构造,则将其修复在一个地方(在视图控制器中),而不是在使用视图控制器的每个地方。

    【讨论】:

    • 如果这是预期的方式,为什么 XCode4 会为每个空的 ViewController 类生成一个 initWithNibName:bundle: stub,但没有 init 方法?
    • 同样的原因,模板没有包含类前缀,即使你肯定应该为你的类添加前缀,并且模板为你的应用程序委托创建了最愚蠢的名称,这真是令人头疼修理。并且 IB 在您自动创建属性时强制声明 ivar,即使您不应该在新 ABI 中声明 ivar。模板并不总是最佳实践。它们通常是在大多数情况下起作用的最小公分母,但在任何地方都不是特别好。 Apple 的示例代码最近在改进,但仍有一段路要走。
    • 如果您遵循将 nib 命名为与类相同的约定,则此代码运行良好:- (id)init { return [super initWithNibName:NSStringFromClass([self class]) bundle:nil]; }
    • @CharlesA 如果您使用这种方法,您可以将nil 作为 nib 名称传递,它会根据视图控制器类计算出来。请参阅 UIViewController -nibName 的文档,该文档解释了它用于查找文件的启发式方法。
    • 我使用这种方法已经有一段时间了。太棒了,谢谢 Rob!
    【解决方案3】:

    在没有 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];
     }
    

    我是这么想的。

    【讨论】:

    • 您知道,如果您将 ~iphone 或 ~ipad 添加到您的 nib 名称中,您只需调用 initWithNibName@"ViewController",它就会选择正确的。
    【解决方案4】:

    只要 xib 与视图控制器类同名,就可以调用 init。封装不是必需的。这样可以节省打字时间,但可能不够清晰。

     NUDMainViewController *mainVC = [[NUDMainViewController alloc] init];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-18
      • 1970-01-01
      • 1970-01-01
      • 2010-10-24
      • 1970-01-01
      相关资源
      最近更新 更多