Iphone – UINavigationController NIB requires File’s Owner to have a view

interface-builderiphoneuinavigationcontrolleruiviewuiviewcontroller

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.

Best Answer

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.