+3  A: 

What you typically do is nest your main ViewController (in this case, PersonListViewController) inside a UINavigationController (like you have done), but then you set the tabBarController.viewControllers property equal to an array of view controllers (one for each tab).

In your case, that would look like

tabBarController.viewControllers = [NSArray arrayWithObject:navController];

Then add only the tabBarController's view to the window

[window addSubview:[tabBarController view];

This will give you your list, inside a nav controller, inside a tab controller (and the tab controller will only have one tab, for now).

jbrennan
+2  A: 

UIWindow doesn't cope well if you try to put views from two view controllers into it: only the last one will get the appropriate callbacks, and they won't know about each other. (I have done this intentionally, when I wanted a constant animated background behind a transparent set of views, but it's tricky.) In ios4 this is more explicit: UIWindow has grown a "rootViewController" property which holds the VC for the window.

What you want here is a tab bar controller containing navigation controllers, one per tab, each containing one of your custom VCs.

sort of like: (this is off the cuff and untested, so watch for errors)

PersonListViewController* plvc = [[[PersonListViewController alloc]
                                    initWithNibName:@"PersonListViewController"
                                             bundle:nil]
                                    autorelease];

UINavigationController *uinc = [[[UINavigationController alloc]
                                  initWithRootViewController:plvc]
                                  autorelease];
// ... make more VCs for any other tab pages here

UITabBarController* tbc = [[[UITabBarController alloc] init] autorelease]; // *1

[tbc setViewControllers:[NSArray arrayWithObjects: uinc, nil]]; // *2

[window addSubview:[tbc view]]; // *3
/* or, if using ios4: [window setRootViewController:tbc]; */

[window makeKeyAndVisible];

at *2, add any VCs for other tabs to the list.

at *3, I believe the window secretly retains the VC, making the release at *1 safe.

Putting nav controllers inside a tab controller is perfectly legit and Apple-endorsed. Putting tab controllers inside nav controllers isn't, though it may work in limited cases.

rgeorge
`UIWindow` is just a `UIView` subclass, and it does not appear to override `-addSubview`, so the default behaviour means `UIWindow` retains the *view* but not the *viewController*.
jbrennan
Yeah, but *something* sneaks a reference to the VC when you add its view to a window, through which the various viewWillAppear, etc., event methods get called. Not sure what. It could be the base UIViewController class itself.Since you typically hang onto your own reference to the root VC for the life of the app (unlike my sloppy sample) it's rarely a real problem.
rgeorge