可以通过编程方式和IB实例化的视图控制器?

时间:2009-06-29 15:57:27

标签: iphone objective-c cocoa-touch

视图控制器FooViewController需要在创建它时进行一些初始化(自身,而不是托管视图 - 在视图加载之前)。

我希望能够以两种方式创建它:

  1. 以编程方式,可能带有一些参数:

    FooViewController *fooViewController = [[[FooViewController alloc] initWithSomeData:data] autorelease];
    [self.navigationController pushViewController:fooViewController animated:YES];
    
  2. 在Interface Builder中。

  3. 对于(1)我会写这样的初始化器:

    - (id)initWithSomeData:(Data *)data     // designated initializer
    {
        if (self = [super initWithNibName:@"FooView" bundle:nil]) {
            self.title = "Foo";
            // perform initialization
        }
        return self;
    }
    - (id)init
    {
        return [self initWithSomeData:nilOrSomeDefaultValue];
    }
    
    // ... other initializers that call the designated initializer
    

    (我对nib名称进行了硬编码,因为控制器总是使用相同的视图配置,因为它使用的视图根本不涉及调用者)

    在Interface Builder中创建时,我希望最终结果与使用无参数init初始化对象的结果相同。

    现在,如果我这样做:

    - (id)initWithCoder:(NSCoder *)decoder
    {
        return [self init];
    }
    

    然后会忽略在Interface Builder中的检查器中设置的titlewantsFullScreenLayoutnibName属性,但这没关系。 nibName在init中是硬编码的,并且title设置在那里,以防控制器以编程方式实例化。

    问题是未设置parentViewController(默认initWithCoder:将根据NIB中的对象层次结构设置它。

    如何从笔尖获取父对象?然后我会将initWithCoder:改为:

    - (id)initWithCoder:(NSCoder *)decoder
    {
        if (self = [self init]) {
            _parentViewController = [decoder parentObject];
        }
        return self;
    }
    

    或者我应该使用一些不同的方法来创建可以通过编程方式和IB实例化的控制器?

2 个答案:

答案 0 :(得分:0)

不要,不要,不要尝试制作一个可以使用和不使用笔尖的viewcontroller。这将是一场噩梦,因为nibloading使用了一些正常的入口点并提供了新的入口点,并且在操作系统修订版中它将是脆弱的。

你可以做的是让视图控制器始终从笔尖加载,然后给自己一个方便的初始化器来完成笔尖:

- (id) init {
  return [[[self class] alloc] initWithNibNamed:@"MyNibName" bundle:nil];
}

然后你可以通过其他nib以正常方式引用它,并在你不想显式处理nib时调用便捷init方法。

答案 1 :(得分:0)

为什么不在viewDidLoad中执行init内容 - 在IB外部创建时,可以在初始化之后但在调用viewDidLoad之前使用其他一些方法或属性设置初始值。