15

I have a my views and controllers set up like so.

  1. A Tab/Bar controller
  2. Within 1. is a root view controller
  3. within 2. is a programmatically created navigation controller, that is displayed as a subview in the root view controller.

What I am trying to do is access the top tab bar/navigation controller so that i can push a view onto it.

I tried parentViewController but all it did was push the view onto the programmed nav controller.

any suggestions?

This is how i set up my root view controller:

  -(void)viewDidAppear:(BOOL)animated{
    NSLog(@"ROOT APPEARED");
    [super viewDidAppear:animated];

    WorklistViewController *worklistController = [[WorklistViewController alloc]initWithNibName:@"WorklistView" bundle:[NSBundle mainBundle]];
    UINavigationController *worklistNavController = [[UINavigationController alloc] initWithRootViewController:worklistController];
    worklistNavController.navigationBar.barStyle = UIBarStyleBlackOpaque;
    worklistNavController.view.frame = watchlistView.frame;
    [worklistNavController.topViewController  viewDidLoad];
    [worklistNavController.topViewController  viewWillAppear:YES];
    [self.view addSubview:worklistNavController.view];

    GetAlertRequestViewController *alertsController = [[GetAlertRequestViewController alloc]initWithNibName:@"AlertsView" bundle:[NSBundle mainBundle]];
    UINavigationController *alertsNavController = [[UINavigationController alloc] initWithRootViewController:alertsController];
    alertsNavController.navigationBar.barStyle = UIBarStyleBlackOpaque;
    alertsNavController.view.frame = alertsView.frame;
    [alertsNavController.topViewController  viewDidLoad];
    [alertsNavController.topViewController  viewWillAppear:YES];
    [self.view addSubview:alertsNavController.view];
}
Matt
  • 2,663
  • 9
  • 27
  • 55

3 Answers3

31

A nested ViewController (ie, inside a view controlled by a ViewController that's actually on the NavController stack) doesn't have direct access to the UINavigationController that its parent's view's controller is a stack member of. That's one MOUTHFUL of a sentence, but the sense of it is: you can't get there from here.

Instead you've got to get at the app's NavController via the App delegate.

YourAppDelegate *del = (YourAppDelegate *)[UIApplication sharedApplication].delegate;
[del.navigationController pushViewController:nextViewController animated:YES];

You're using your UIApplication's singleton (contains all sorts of good info about your app), which has a .delegate property pointing to the AppDelegate, and that contains a reference to the NavigationController.

This is how the "Navigation-based Application" Xcode template sets up NavController ownership, anyway. YMMV if you rolled your own--though if you did, you probably wouldn't need to ask this question.

Dan Ray
  • 21,345
  • 6
  • 61
  • 86
  • 1
    With iOS 4.0 as deployment target, the code 'del.navigationController' makes a build error : "Request for member navigationController in something not a structure or union" – Marcel Falliere Nov 22 '10 at 17:40
  • @Marcel--Your application delegate HAS a navigation controller as a named property, right? – Dan Ray Nov 22 '10 at 18:04
  • 1
    error: property 'navigationController' not found on object of type 'AppDelegate *' – Dawid Drozd Aug 03 '16 at 13:32
  • This only works if you store the navigation controller in your app delegate. This is not standard. – Mike C. Sep 18 '18 at 20:34
10

You can use the follow instruccion:

[(UINavigationController *)self.view.window.rootViewController pushViewController:vc animated:YES];

It works for me :D

codercat
  • 21,439
  • 9
  • 56
  • 84
JERC
  • 1,499
  • 3
  • 16
  • 36
0

Have a look at UIViewController's navigationController and tabBarController properties. These will return the corresponding navigationController or tabBarController that the given UIViewController 'belongs' to.

So you can do something like:

[customController.navigationController pushViewController:newController animated:YES];
// Similarly for tabBarController ...
sasquatch
  • 6,126
  • 7
  • 39
  • 56
nebs
  • 4,869
  • 9
  • 37
  • 68
  • 1
    I am a little confused at what you mean. The stack would look like this. 1.Navigation Controller -> RootViewController -> 2.Navigation Controller -> AViewConroller And what i want is for AViewController to push a new viewcontroller on to 1.Navigation Controller. But No matter what i try it keeps pushing it onto 2.Navigation Controller? If that makes it clearer idk. Sorry. – Matt Jun 29 '10 at 15:46
  • Hey, I updated my post to match your comment. It's a little strange to stack two navigation controllers since one does the same thing as the other one. Anyways checkout my suggestion as it might work, but I'm not 100% sure. – nebs Jun 29 '10 at 16:03
  • Sorry I know it is strange I didn't really give a background. I have a tab bar controller that has 3 tab/controllers. 1. Home 2. Search 3. Settings. Within the root view there are 3 diffrent tables that have navigation controlles->table view controllers. These show alerts, a watchlist, and previous searches. So in the watchlist view controller when you press view documents arrow i want it to take over the top navigation controller so it shows the whole screen. But unfortunatly that code you gave me did not work. – Matt Jun 29 '10 at 16:23
  • Ok I'm confused as to what you actually want. What do you mean by "take over the top navigation controller so it shows the whole screen"? Your initial question was how to access a navigation controller from one of its stacked view controllers and for that you use the navigationController property. So from any of the stacked view controllers you can call navigationController to access the 'parent' navigation controller. Maybe you can edit your original question with more detail because I'm not sure I follow exactly. – nebs Jun 29 '10 at 17:55
  • Sorry not take over, just push a view. And my Question is how to get the original stack, not the second stack. – Matt Jun 29 '10 at 18:07