views:

3353

answers:

4

I'm trying to get multiple levels of hierarchy working with Navigation Controllers. I have 3 levels of hierarchy and I can move down through the levels of hierarchy, but I can only go back one level and not two levels, back to the starting view.

I start by creating a navigation controller for View #1 and push the next view, View #2, onto it. Then I add the navigation controller to the subview of the window in didSelectRowAtIndexPath. Clicking on a table row in View #1 , takes me to the next hiearchy level View #2.

This next hiearchy level view is also a table view. Here is where I think the problem occurs. I create another navigation controller and push View #3 onto it in didSelectRowAtIndexPath in the View Controller for View #2. Clicking on a table row in View #2 takes me to View #3. But when I use the back button to go back to View #2, I go back to an empty view, and not the real View #2.

  1. Do I only need one navigation controller to handle 3 levels of hiearchy instead of two navigation controllers?

  2. If #1 is yes, then how do I pass the navigation controller to view #2's controller so that I can push View #3 onto the navigation controller?

  3. Or do I need to push all three views onto the navigation controller in View #1?

  4. Or...?

Thanks in advance,

Jim

+1  A: 

In general all of your hierarchy should be contained in a single UINavigationController. I am not sure if nesting them is even supported.

Andrew Grant
+3  A: 

The UIViewController has been designed to work hand in hand with UINavigationController. When pushing a new view, a UINavigationController will inject references to itself and to a UINavigationItem containing metadata about the navigation (back button with the title of the view behind it etc...).

Generally, you want to initialize your UINavigationController with Interface Builder using the "NIB Name" field to specify the "root view controller" (i.e. the first view to appear which should not have a back button). The equivalent in code roughly looks like this:


UIViewController *rootController = [[UIViewController alloc] initWithNibName:@"RootController"];
UINavigationController *navCtl = [[UINavigationController alloc] initWithRootController:rootcontroller];

Then, when you need to push a new view controller (probably in your didSelectRowAtIndexPath delegate method in your rootController)


SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController"];
[self.navigationController pushViewController:secondViewController];
[secondViewController release];

Notice that you didn't have to create the self.navigationController property, it is already defined in UIViewController and will be injected with the right reference depending on the current state of the navigation. It works like magic!

François P.
Thanks for your answers. I'm still a bit confused. You have *navCtlbut then use self.navigationController. Should that be self.navCtl?
The first code snippet would be in the application delegate; the second would be in the root view controller.
Brent Royal-Gordon
+2  A: 

The DrillDownSave sample code from the Apple Developer site:

https://developer.apple.com/iphone/library/navigation/SampleCode.html

does exactly what I am looking for with three hierarchy levels of views using the navigation controller. Thanks for your answers.

Jim

The link here doesn't work anymore. It redirects to the index of iphone related docs at apple.
Kevin McMahon
Here's a link: http://developer.apple.com/iphone/library/samplecode/DrillDownSave/ Also the UINavigationBar Class Reference has links to three other samples.
progrmr
A: 

How would you do this IF the subsequent views are additional instances of the same controller, that is a true hierarchy of nothing more than table views... the example shows hard coded views... but they essentially do the same thing. My OO background says if I alloc/init a new instance of a controller, shouldn't I be able to push that, then have its state restored on pop (back button)? That doesn't seem to work for me. Each instance of the controller (UITableViewController) has its own instance of an array as its data...

You should ask this as a separate question.
jm