【问题标题】:UIViewController: [super init] calls [self initWithNibName bundle:]UIViewController: [super init] 调用 [self initWithNibName bundle:]
【发布时间】:2012-11-22 04:40:19
【问题描述】:

我的 UIViewController 子类中有两个初始化函数:

- (id)init
{
    self = [super init];
    if (self)
    { 
           // Custom stuff
        return self;
    }
    return nil;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName: nibNameOrNil 
                           bundle: nibBundleOrNil];
    if (self) 
    {
        // Custom stuff
    }
    return self;
}

我将 init 函数放入以避免调用 initWithNibName:bundle: 方法。我正在尝试取出 xib 文件。不幸的是,调用这个 init [[Myclass alloc] init] 通过调用 [super init] 调用 initWithNibName:bundle:。

首先,我应该在文档中的哪个位置阅读,以便我期望对父 init 方法的调用调用我自己的 initWithNibName:bundle: 方法?

其次,这对 Apple 来说是一个好的设计选择。我不明白为什么这是可取的行为? (可能是我在这里没有了解全局,所以请随时提示我。)

第三,我怎样才能最好地绕过它。我只是从我的代码中取出 initWithNibName:bundle: 吗?有没有我想要选择使用 xib 或手动实例化类的情况。

【问题讨论】:

  • 你确定它正在进入你的 -(id)init 函数吗?您是否也在头文件中声明了您的 init 函数?
  • @snaker -init 来自 NSObject 本身,不需要声明。

标签: objective-c ios uiviewcontroller xib


【解决方案1】:

通常我必须使用托管对象上下文来初始化我的视图控制器。我实现了简单的-(id)initWithContext: 方法,在该方法中我调用了super 的initWithNibName:bundle: 方法。这样我就可以定义自己的 xib 名称了。

不确定您问题的第一部分(即阅读内容),但 Apple 的 VC 类模板显示它们有自己的 initWithNibName:bundle 方法,该方法使用与给定参数相同的参数调用 super。因此,根据您的情况,我想说这正是指定的初始化程序,在 super 上调用简单的init 方法是不“安全的”,因为它将调用initWithNibName:bundle。我相信 UIViewController 的 init 看起来是这样的:

- (id)init
{
  self = [self initWithNibName:nibNameDerivedFromClass bundle:probablyNilOrMainBundle];

  if (!self) return nil;

  // some extra initialization

  return self;
}

由于超类没有initWithNibName:bundle,它必须自己调用方法,使其成为指定的初始化程序。由于您已覆盖它,ObjC 的运行时会将该方法中的 self 替换为您的类。

【讨论】:

    【解决方案2】:

    如果您想在创建 UIViewController 的 GUI 时排除 Interface Builder,您必须覆盖 loadView 并自己创建视图。不要实现initWithNibName:bundle:

    - (void)loadView {
        // Init a view. The frame will be automatically set by the view controller.
        UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
    
        // Add additional views (buttons, sliders etc.) to your view here.
    
        // Set the view controller's view to the new view.
        self.view = view.
    }
    

    【讨论】:

      【解决方案3】:

      首先,我应该阅读文档的哪个位置 期望调用父初始化类来调用我自己的 initWithNibName:bundle: 方法?

      你不知道,这是一个设计问题。 init 不是所有类的基本初始化方法

      其次,这对 Apple 来说是一个好的设计选择吗?我不是 明白为什么这是可取的行为? (可能只是我不是 在这里了解全局,所以请随时为我提供线索。)

      init 调用它时,它会发送 nil 名称和包,并且默认为一个空的 xib 文件。总有一个 xib 文件,不管你的与否。

      第三,我怎样才能最好地解决它。我只是采取 initWithNibName:bundle: 超出我的代码范围?有没有我 想要使用 xib 或手动实例化的选项 类的。

      你没有。如果你只是调用 super ,只是转发一个方法,你真的不需要有那个代码。

      【讨论】:

        【解决方案4】:

        您可以自定义视图并在 viewDidLoad 方法中添加子视图。在此方法中,您可以通过检查属性 nibName 来检查类是使用 init 还是使用 initWithNibName:bundle: 创建的。使用 init 时,nibName 将为 nil。

        - (void)viewDidLoad
        {
            [super viewDidLoad];
            if (!self.nibName) {
                // View was not loaded from nib - setup view
            }
        }
        

        【讨论】:

        • 这个方法在初始化之后调用。
        • @DrummerB 您不必重写 loadView,如果您不这样做,则会在您第一次引用 self.view 时为您创建一个。
        猜你喜欢
        • 2012-02-21
        • 2011-03-04
        • 1970-01-01
        • 1970-01-01
        • 2012-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多