5

我的 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: 方法?

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

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

4

4 回答 4

6

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

不确定您问题的第一部分(即阅读内容),但 Apple 的 VC 类模板表明它们有自己的initWithNibName:bundle方法,该方法使用与给定参数相同的参数调用 super。因此,根据您的情况,我会说这正是指定的初始化程序,并且init在 super 上调用简单方法并不“安全”,因为它将调用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在该方法中替换为您的类。

于 2012-12-04T14:20:00.133 回答
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.
}
于 2012-12-04T14:19:09.770 回答
0

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

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

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

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

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

你没有。如果您只是调用超级,您实际上并不需要那里有该代码,而只是转发一个方法。

于 2012-12-04T14:19:28.590 回答
-3

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

- (void)viewDidLoad
{
    [super viewDidLoad];
    if (!self.nibName) {
        // View was not loaded from nib - setup view
    }
}
于 2012-12-04T15:58:18.960 回答