Rob Jones
Rob Jones

Reputation: 4985

How should I manage swapping a UINavigationController in and out of another UIViewController?

Here's what I have:

When the application launches both ivars are initialized from their respective nibs, and then the UIViewController.view is added as a subview of RootViewController.view.

Inside UIViewController's view I have a control that triggers an animated swap of UIViewController and UINavigationController. This is where the problem comes in. The swap animates, but the UINavigationController's views are not properly displayed. I get a Navigation Bar with no title, and nothing else.

The UINavigationController nib and underlying functionality have been tested in a stand alone project, but there was no RootViewController.

So, my question is, can I even do this? I've successfully swapped other view controllers like this, but never a UINavigationController. I've seen some documentation that leads me to believe this might be a fools errand, but I haven't convinced myself of that yet.

Solution (Kinda):

I found a solution (workaround? hack?), but it leads to some more questions. I nixed using a Nib for the UINavigationController. Instead, I loaded my UINavigationController's rootViewController from a Nib and then created the UINavigationController programmatically with initWithRootViewController:.

  NavRootViewController *navRoot = [[NavRootViewController alloc] initWithNibName:@"NavRootViewController" bundle:nil];
  navigationController = [[UINavigationController alloc] initWithRootViewController:navRoot];
  [navRoot release];

This works as I expect. Which leads me to the conclusion that the rootViewController property of the UINavigationController wasn't being set properly when I loaded navigationController from a Nib. And the question is, why? Should it?

Upvotes: 0

Views: 1267

Answers (3)

greggwon
greggwon

Reputation: 61

In some cases, viewDidLoad and viewDidAppear or awakeFromNib may need to be called each time you add the UINavigationController back into the stack of UIViewControllers. It seems that when the typical code executes out of your AppDelegate, that the Window, or something behind the scenes is doing something special for UINavigationController that presentModalViewController doesn't do.

Upvotes: 1

greggwon
greggwon

Reputation: 61

Also, when you see something like this happening in one case, but not another, it can be beneficial to either create a subclass and make your nib point at that subclass, or if you already have a subclass use that.

In the subclass, override all the various init:, initWithNibName:bundle:, viewDidLoad:, viewWillAppear:, viewDidAppear: and any other appropriate methods, and in those override, just NSLog("") something about which method it is (with param values perhaps) and call the super implementation.

This will give you an observable "track" of which methods are called in which order, and you can set a breakpoint to see where that call comes from.

This will give you enough information to find missing method calls, and then you can pursue the correct problem either here, or through filing a radar or ...

Upvotes: 1

TechZen
TechZen

Reputation: 64428

I think you may have missed a conceptual point.

A UINavigationController controls view controllers instead of views. It controls when and where view controllers themselves are loaded. The views themselves are loaded only as a side effect of the pushing and popping of their respective controllers.

Therefore, putting a navigation controller inside of a view controller seldom makes much sense.

If I understand what you are trying to do correctly, you should have the RootController actually set as the rootController property of the UINavigationController (yes the nomenclature is extremely confusing.) Then when your swap event occurs, you should have the navigation controller push the next view. The RootController view will disappear to replaced by the other. then you can repeat the process for an arbitrary number of view controllers.

Only in the case of a tabbar would you want a navigation controller to be a property of a view controller. Even then it should be at the top the tab's hierarchy.

Upvotes: 0

Related Questions