如何使用可由多个ViewControllers使用的关联View类创建Nib

时间:2010-01-14 18:30:05

标签: iphone cocoa uiviewcontroller nib

我正在打开一个新问题来跟进我的最后一个问题(superview and parentviewcontroller nil after adding a subview)。基本上我认为使用子视图是一个好主意,但我不应该有一个ViewController控制住在另一个ViewController中的子视图。基本上我想做以下事情...... 我有两个ViewControllers,它们共享一个共同的子视图。我已经将该子视图创建为一个名为SearchDate.xib的笔尖。文件所有者是相应的类SearchDateView.m / h。该类有一个出口,用于nib中UIView内部唯一的元素,它是一个标签。 SearchDateView类还具有更改SearchDateView.xib中标签值的功能。我希望我的两个ViewControllers加载这个笔尖,但显然我不知道如何正确加载笔尖。无论我做什么,最好什么都不显示,最坏的情况是抛出异常。苹果文档谈到将IB中其他类的实例拖入主视图,但这似乎没有成功。我的ViewController中有一个SearchDateView插座,我尝试在控制器的加载视图上执行此操作:

searchDateView = [[[NSBundle mainBundle] loadNibNamed:@"SearchDateView" owner:self options:nil] objectAtIndex:0];
[[self view] addSubview:searchDateView];

但我得到了这个例外:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MainViewController 0x431fac0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key searchDateLabel.'

我知道我做了一些完全错误的事情,但是有一个nib,关联的视图类更新该nib中的一些对象,并在不同的控制器中重用该nib的正确方法是什么?

编辑:鉴于评论或许这不够明确。我不想在整个ENTIRE视图中使用相同的nib文件 - 而是使用子视图。因此,例如,控制器A具有映射和SearchDateView,控制器B具有表视图和SearchDateView。所以我想知道如何将子视图加载到多个控制器......

2 个答案:

答案 0 :(得分:2)

当使用initWithNibName初始化每个控制器时,使用相同的NIB文件应该没有问题:bundle:。您通常不会从控制器内加载控制器自己的nib文件。

如果使用loadNibNamed :::加载nib文件,则会获得其中定义了对象的NSArray,因此您无法直接将其用作视图。获取视图的一种方法是使用for()或某些东西搜索数组以找到所需的对象,但是如果你设置owner:self,那么它应该连接到连接到File的所有者的出口,因为文件的所有者将是自己的。但是你可以在这种情况下丢弃返回值;你不需要返回的数组。如果您连接了该插座,这可能是您的主要问题(用阵列破坏插座)。

可以使用loadNibNamed来加载特定的视图对象(假设你从返回的数组中选择它),然后以某种方式显示它,但通常更容易在控制器上使用initWithNibName(在这种情况下,File的所有者将是控制器)。

哦,您还可以在Interface Builder中为控制器设置nib文件。对于多个控制器使用相同的nib应该没有问题,因为基本上你只是告诉Interface Builder设置nib文件来执行类似initWithNibNamed的操作。单击控制器对象并检查检查器窗口。

<强>更新

为了在多个控制器中只使用一个视图,我可能会这样做:

    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"FooView" 
                                                 owner:self options:nil];
    for (id obj in nib)
        if ([obj isKindOfClass:[FooView class]])
            myNewView = (FooView *)obj;

(来自开始iPhone 3开发的示例代码中的第8章:单元格2)。

你可以用IB中的插座来做这件事,在这种情况下你可以省略for循环,但你可能需要一个超类来为两个控制器声明插座,并告诉Interface Builder File的Owner是一个实例那个超类的所以它知道出口。可能不值得麻烦。

答案 1 :(得分:0)

  

我的ViewController中有一个SearchDateView插座,我尝试在控制器的加载视图上执行此操作:

searchDateView = [[[NSBundle mainBundle] loadNibNamed:@"SearchDateView" owner:self options:nil] objectAtIndex:0];
[[self view] addSubview:searchDateView];
     

但我得到了这个例外:

 *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MainViewController 0x431fac0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key searchDateLabel.'

如果没有Cocoa Bindings(只有Cocoa,而不是Cocoa Touch),我不认为这两者是相关的。

在Xcode中,在objc_exception_throw上添加符号断点,然后在调试器中运行您的应用。当它中断时,查看调用堆栈。您将能够找到问题的真正来源。