UINavigationController NIB需要File's Owner拥有一个视图吗?

6

我在设置视图控制器的nib默认视图插座时遇到了问题,这里是我的设置:

我有一个TabBar应用程序,在其中将一个导航控制器作为模态视图加载...

MyNavCtrlrSubClass *menu = [[MyNavCtrlrSubClass alloc]initWithNibName:@"MenuController" bundle:nil];
[tabBarController presentModalViewController:menu animated:anim];

MenuController本身的结构如下:

MenuController.xib
  File's Owner(MyNavCtrlrSubClass:UIViewController)
  Navigation Controller(UINavigationController)
    Navigation Bar(UINavigationBar)
    Root View Controller(Nib名称设置为加载AnotherViewController.nib)
      Navigation Item ->(UINavigationItem)

这一切都很好,但是当加载MyNavCtrlrSubClass时,我会得到以下错误:

Loaded the "MenuController" nib but the view outlet was not set

显然出现这种情况是因为File's Owner没有用于视图的outlet connection。问题在于我应该将什么设置为它的视图,或者是否需要首先进行某些设置? Navigation Bar是MenuController.xib中唯一的候选对象,但这只会使UINavigationBar本身充满全屏模式,那么怎么办呢?

显然,在IB中我漏了什么。除了一个用于UINavigationController的IBOutlet之外,MyNavCtrlrSubClass.m中没有任何代码。我在尝试完全在IB中设置这个的时候是不是犯了一个错误?我的想法是将模态导航控制器保留在一个nib文件中,并将其加载的所有视图保留在单独的nib文件中,但由于MenuController只是导航的容器而不包含任何视图,所以我显然设计得不对。 :)

如果你想知道为什么我不以其他方式设计它,那是因为我试图遵守我的(可能错误的)感觉,即IB要求您构建理想层次结构的方式。

非常感谢任何帮助。

3个回答

5
我想你可能不理解在NIB文件中如何使用“文件所有者”。我已经写了一篇回答,描述了文件所有者的另一个问题
当您调用此行时:
[[MyNavCtrlrSubClass alloc] initWithNibName:@"MenuController" bundle:nil]

您需要创建一个MyNavCtrlrSubClass实例,并告诉它加载@"MenuController"。然后,在MenuController.xib文件中,有第二个不相关的UINavigationController及其中的内容。当在运行时加载MenuController.nib时,将会创建该第二个导航控制器。
第二个问题是,告诉UINavigationController加载NIB文件并不是真正合理的,因为导航控制器会创建和管理它们自己的视图。您真正想要的是创建根视图控制器,并告诉该视图控制器加载NIB文件。
请尝试这样做:
MyRootViewController *rootController = [[[MyRootViewController alloc] initWithNibName:@"AnotherViewController" bundle:nil] autorelease];
MyNavCtrlrSubClass *menu = [[MyNavCtrlrSubClass alloc] initWithRootViewController:rootController];

当你的XIB文件看起来像这样:

  • 文件所有者(类设置为MyRootViewController,视图插座连接到后续UIView)
  • UIView
    • 子视图A
    • 子视图B

在你熟悉所有这些工作方式之后,你还可以考虑在一个XIB文件中实例化导航控制器和根视图控制器,就像你在发布的代码中开始做的那样。


感谢您提供的信息性回复!我将尝试利用这些内容,很快就会回复您。现在,让我问一下:如果要尽可能多地使用Interface Builder设计,那么如何加载模态导航控制器nib呢?是否像您的示例中那样需要设置一个视图控制器nib,然后通过编程方式创建导航控制器,还是可以仅在IB中定义视图层次结构? - Travis Dunn
注意:似乎以编程方式创建导航控制器也意味着我必须以编程方式设置其自己的视图控制器层次结构,然后我离开IB越来越远,从导航控制器开始。 - Travis Dunn
1
您可以在代码中创建导航控制器和根视图控制器,并在IB中加载根视图控制器的视图。这不会很尴尬。您还可以在与根视图控制器的视图不同的XIB中创建导航控制器和其根视图控制器。这个单独的XIB通常是MainWindow.xib。当加载MainWindow.xib文件时,将创建这两个视图控制器。当根视图控制器首次需要它的视图时,它将从第二个XIB文件中加载它。这是通常的做法。 - Jon Hess

1
这个问题的关键在于Travis本人所说的:“如何加载导航控制器nib,在Interface Builder中尽可能地设计?”而且从例子中看来,这意味着UINavigationController和相关的UIViewControllers。
根据这种解释,答案是你不能在一个单独的XIB中完全配置UINavigationController和它的UIViewControllers。是的,想要这样做是很直观的,这样你就不会疯了。
当我说你不能这样做时,我的意思是最常用的框架方法没有处理这种方式的方法。没有[UINavigationController alloc] initWithMegaNibName。是的,你可以把几乎任何东西都塞进一个单独的XIB中,并编写代码以特殊的方式填充对象,但我认为这不是你想要的。
你可以像Jon建议的那样使用两个或更多的XIB,但这样事情就不是那么自包含了,所以有很多人发现在代码中做部分或全部控制器更简单。
不幸的是,在其他开发平台上,Interface Builder的能力与代码之间没有1:1的对应关系。我通常更喜欢让设计师尽可能参与创建资产,但我认识的大多数设计师都不会编写Objective-C代码。

0
在IB中,在MenuController nib中添加一个UIView并将该视图设置为outlet。您需要为UIViewController设置该视图。这里是一个快速链接,指向一个苹果页面,展示了基本的设置。不确定它是否能帮助您在当前阶段。

问题在于我的导航控制器nib中没有视图可以连接。我的限制是要将每个单独的nib分开,因此我的问题是概念或设计方面的,而不是实现方面的问题。无论如何,谢谢。 - Travis Dunn
AnotherViewController 设置了哪个视图?看起来问题就出在那里。 - Jordan
AnotherViewController只是一个具有单个视图的视图控制器nib。尽管它甚至没有被加载,但问题出现在MenuController想要一个视图的生命周期某个地方,但它并没有像我希望的那样自动向下传播请求到控件中,而是抛出了上述错误。根据您的回答,似乎您在暗示nib的“文件所有者”不一定需要一个nib。这是您的理解吗? - Travis Dunn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接