如何使用顶级ViewController加载XIB?

时间:2013-09-25 09:59:52

标签: ios uiview uiviewcontroller interface-builder xib

我有一个带有视图控制器根元素的笔尖,如下所示:

enter image description here

所以我可以使用自动布局相对于顶部和底部布局指南定位元素。

当我第一次尝试使用

加载此笔尖时
SearchViewControllerPro* searchViewController = [[SearchViewControllerPro alloc]initWithNibName:@"SearchViewControllerPro" bundle:[NSBundle mainBundle]];

我遇到了以下运行时异常:

  

由于未捕获的异常而终止应用   'NSInternalInconsistencyException',原因:' - [UIViewController   _loadViewFromNibNamed:bundle:]加载了“SearchViewControllerPro”笔尖,但未设置视图插座。'

搜索我指出的错误,需要将xib的文件所有者设置为我的视图控制器的类,并且必须将视图插件设置为xib中的视图对象。如果我这样做,那么我得到以下运行时错误:

  

由于未捕获的异常而终止应用   'UIViewControllerHierarchyInconsistency',原因:'视图只能是   一次最多与一个视图控制器相关联!查看>与....关联 。在将此视图与之关联之前清除此关联   。“

由于视图与文件所有者和nib的顶级视图控制器相关联,因此不会出人意料。但是,我怎么能告诉运行时它们实际上是同一个东西而不是两个独立的实体呢?

修改 当我尝试从nib中取消ViewController时,

NSArray* xibContents = [[NSBundle mainBundle] loadNibNamed:@"SearchViewControllerPro" owner:nil options:nil];
SearchViewControllerPro* mapSearchViewController = [xibContents lastObject];

,它也没有好处:

  

由于未捕获的异常'NSUnknownKeyException'而终止应用,   reason:'[setValue:forUndefinedKey:]:这个类   密钥视图不符合密钥值编码。

临时解决方案:

我找到了一个解决方案,但它并不漂亮。尽管IB中显示了结构,但视图控制器不是xib中的最后一个对象。所以我有:

__block SearchViewControllerPro* mapSearchViewController = nil;
[xibContents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    if ([obj isKindOfClass:[SearchViewControllerPro class]]) {
        mapSearchViewController = obj;
    }
}];

这似乎没有运行时崩溃。但是,它只是干净的代码。

3 个答案:

答案 0 :(得分:4)

  

我怎么能告诉运行时它们实际上都是一样的   事情而不是两个独立的实体?

你不能,因为他们不是一回事。您已创建了两个SearchViewControllerPro个实体。

你需要在一个nib上为alloc-init一个SearchViewControllerPro实例或unarchive一个。

如果您决定在笔尖中创建ViewController,通常的访问方式与访问您在笔尖中创建的任何其他项目(视图,按钮,文本字段)的方式相同。

向FilesOwner对象添加一个插座,在接口构建器中挂接连接,并确保在取消归档nib时传递该对象。

例如,如果您希望取消归档nib的Object为FilesOwner:

[[NSBundle mainBundle] loadNibNamed:@"SearchViewControllerPro" owner:self options:nil];

答案 1 :(得分:3)

以下工作原理(至少对我而言)更明确一点,即为ViewController创建一个插座:

NSArray* xibContents = [[NSBundle mainBundle] loadNibNamed:@"SearchViewControllerPro" owner:nil options:nil];
SearchViewControllerPro* mapSearchViewController = [xibContents objectAtIndex:0];

答案 2 :(得分:0)

if (isIPad)
{
    [[NSBundle mainBundle] loadNibNamed:@"ABC_iPad" owner:self
options:nil];

}
else{
    [[NSBundle mainBundle] loadNibNamed:@"ABC_iPhone" owner:self options:nil];

}