views:

3557

answers:

2

I'm having a problem setting a View Controller nib's default View Outlet in Interface Builder. Here's my setup:

I have a TabBar based application where I load a Navigation Controller as a modal view...

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

MenuController itself is structured as follows:

MenuController.xib
  File's Owner (MyNavCtrlrSubClass : UIViewController)
  Navigation Controller (UINavigationController)
    Navigation Bar (UINavigationBar)
    Root View Controller (Nib Name is set to load AnotherViewController.nib)
      Navigation Item -> (UINavigationItem)

This all works fine, except that when MyNavCtrlrSubClass is loaded, I get the following error:

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

It's clear why this is happening - File's Owner doesn't have an outlet connection for its view. The question is what should I set as its view, and does something have to be set in the first place? The Navigation Bar is the only candidate in MenuController.xib, but doing this will just size the UINavigationBar itself to the fullscreen mode, so to speak.

I'm obviously missing something in IB, but what? MyNavCtrlrSubClass.m has no code itself, except an IBOutlet for the UINavigationController. Am I making a mistake trying to set this up entirely in IB? The idea is to keep the modal Navigation Controller in one nib, and all the views it loads in separate nibs, but since MenuController is just a container for the navigation and contains no views itself, I'm obviously designing it wrong. :)

If you're wondering why I'm not designing it some other way, it's because I'm trying to obey my (possibly mistaken) perception of how IB asks you to build an ideal hierarchy.

Any help would be greatly appreciated.

A: 

In IB, in the MenuController nib add a UIView and set that view as the outlet. You will need to set that view for a UIViewController. Here is a quick link to an Apple page showing a basic setup. Not sure if it will help you at your current stage though.

ryanday
The problem is that there is no view in my navigation controler nib to hook up. The constraints are that I want to separate each individual nib, so my problem is conceptual- or design-oriented, not a problem of implementation. Thanks in any event.
Travis Dunn
What view is set for AnotherViewController? Looks like that's where the problem is.
Jordan
AnotherViewController is just a View Controller nib with a single view. It's not even being loaded, though. The problem occurs somewhere in the lifecycle when MenuController wants a view, but instead of what I hoped would be automagically propagating the request down the controls, it just throws the aforementioned error. By your answer, though, it sounds like you're implying a nib's File's Owner doesn't necessarily need a nib. Is that your understanding?
Travis Dunn
+1  A: 

I think you might not be understanding how the File's Owner is meant to be used in a NIB file. I've written up a response describing the file's owner under another question.

When you invoke this line:

[[MyNavCtrlrSubClass alloc] initWithNibName:@"MenuController" bundle:nil]

You create an instance of MyNavCtrlrSubClass, and tell it to load @"MenuController". Then in the MenuController.xib file, there is a second unrelated UINavigationController with things inside of it. When MenuController.nib is loaded at runtime, that second navigation controller will be created.

A second problem is that telling a UINavigationController to load a NIB file isn't really sensible because navigation controllers create and manage their own views. You really want to create the root view controller, and tell that view controller to load a NIB file.

Try this:

MyRootViewController *rootController = [[[MyRootViewController alloc] initWithNibName:@"AnotherViewController" bundle:nil] autorelease];
MyNavCtrlrSubClass *menu = [[MyNavCtrlrSubClass alloc] initWithRootViewController:rootController];

Where your XIB File looks like this:

  • File's Owner (Class set to MyRootViewController, view outlet connected to subsequent UIView)
  • UIView
    • Subview A
    • Subview B

After you're confortable with how all of this is working, you might also consider instantiating the navigation controller and root view controller in one XIB file like you were starting to do in the code you posted.

Jon Hess
Thanks for informative reply! I'm about to see what I can do with this, and will post back shortly. For now, let me just ask: how then would you load a modal Navigation Controller nib, designing as much as possible in Interface Builder? Is it necessary, as in your example, to set up a View Controller nib and then create the Navigation Controller programmatically, or can I define the view hierarchy in IB alone?
Travis Dunn
NOTE: it seems like creating the Navigation Controller programmically would mean I also have to set up its own view controller hierarchy programmatically, and then I'm getting further and further away from IB, starting with the navigation controller on down.
Travis Dunn
You can create a navigation controller and root view controller in code, and load the view for the root view controller in IB. It won't be awkward. You can also create the navigation controller, and it's root view controller in a separate XIB from the root view controller's view. This separate XIB is typically the MainWindow.xib. When the MainWindow.xib file is loaded the two view controllers will be created. When the root view controller first needs it's view, it will load it from the second XIB file. That's the typically way to do this.
Jon Hess