IOS ViewController navigation path - how to navigate back programatically

20,534

Solution 1

This is an old question, but just to help anyone else who comes across this issue, there's a single command which'll make your life easier..

[self.navigationController popToRootViewControllerAnimated:TRUE];

Easy when you stumble across the right command, isn't it !

So, supposing you had a series of three screens in a Navigation Controller, and on the third screen you wanted the "Back" button to take you back to the initial screen.

-(void)viewDidLoad
{
    [super viewDidLoad];

    // change the back button and add an event handler
    self.navigationItem.leftBarButtonItem =
    [[UIBarButtonItem alloc] initWithTitle:@"Back"
                                     style:UIBarButtonItemStyleBordered
                                    target:self
                                    action:@selector(handleBack:)];
}


-(void)handleBack:(id)sender
{
    NSLog(@"About to go back to the first screen..");
    [self.navigationController popToRootViewControllerAnimated:TRUE];
}

Solution 2

After some research using this and a couple other questions for modal UIViewControllers in storyboard to go back two views I used

[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];

Solution 3

Going throw an old response tough of updating it to be more complet.
To address this question :

Can someone explain the navigation hierarchy and how to traverse the chain backwards programatically?

The structure of your navigation :

tabbarVC --> navigationVC-1 --> tableVC-1 --(via segue push)-> tableVC-2 --(via segue modal)-> navigationVC-2 --> tableVC-3

Can be explain like this :
The TabbarVC is showing it's 'selectedViewController' (navigationVC-1).
NavigationVC-1 has its navigation stack compose of TableVC-1 and TableVC-2 (topViewController of NavigagtionVC-1)
Then NavigationVC-2 is presented Modally over the tabbarVC, so tabbarVC is the presentingViewController and NavigationVC-2 is the presentedViewController

So in order to reach tableVC-2 from tableVC-3 you would need to do something like this :

[(UINavigationController *)[(UITabBarController *)[tableVC-3 presentingViewController] selectedViewController] topViewController];

(don't do that in production code)

[tableVC-3 presentingViewController] as well as [tableVC-3.navigationController presentingViewController] will give you back the UITabBarController.


If you are using a UINavigationController you should use it's push and pop method to put UIViewController on or off the "presentation stack".
You will be able to access the UINavigationController from those UIViewController like this:

self.navigationController

If you want to go back more than one UIViewController on the "presentation stack" you can use this method on the UINavigationController

popToViewController:animated:
Pops view controllers until the specified view controller is at the top of the navigation stack.
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated


To dismiss a UIViewController that was presented modally, the UIViewController that have presented it need to dismiss it with :

- (void)dismissModalViewControllerAnimated:(BOOL)animated

So in this case it should be :

[tableVC-2 dismissModalViewControllerAnimated:YES];
Share:
20,534
mpprdev
Author by

mpprdev

Updated on June 10, 2020

Comments

  • mpprdev
    mpprdev about 4 years

    I'm using IOS5 Storyboard. My View Controller path is as follows:

    tabbarVC --> navigationVC-1 --> tableVC-1 --(via segue push)-> tableVC-2 --(via segue modal)-> navigationVC-2 --> tableVC-3
    

    In the cancel button callback action method in tableVC-3 I call [self dismissViewControllerAnimated:YES completion:nil]; that successfully gets me back to tableVC-2. However when I try to examine the navigation path backwards in the debugger, I don't see a way to access tableVC-2 from navigationVC-2. I expected navigationVC-2 to maintain a link to tableVC-2 or navigationVC-1 but it doesn't seem to. Please see my debugger output below.

    Can someone explain the navigation hierarchy and how to traverse the chain backwards programatically?

    (gdb) po self
    <tableVC-3: 0x6d33340>
    
    (gdb) po (UIViewController*) [self navigationController]
    <UINavigationController: 0x6d33560>
    
    (gdb) po (UIViewController*)[[self navigationController] navigationController]
    Can't print the description of a NIL object.
    
    (gdb) po (UIViewController*)[[self navigationController] topViewController]
    <tableVC-3: 0x6d33340>
    
    (gdb) po (UIViewController*)[[self navigationController] presentingViewController]
    <UITabBarController: 0x6b2eba0>
    
    (gdb) po (UIViewController*)[[self navigationController] presentedViewController]
    Can't print the description of a NIL object.
    
    (gdb) po (UIViewController*)[[self navigationController] visibleViewController]
    <tableVC-3: 0x6d33340>
    
  • mpprdev
    mpprdev over 12 years
    Actually my question is different. Notice that I have 2 navigation controllers in play. My question is how to get back to the first navigation controller. If you see the debug output I pasted, there doesn't seem to be any way to traverse back to the first navigation controller.
  • mpprdev
    mpprdev over 12 years
    thanks for the comments. Without the 2nd nav controller, the 'modal' type segue doesn't seem to work (app crashes).
  • Vincent Bernier
    Vincent Bernier over 12 years
    @mpprdev - Ok I get it, I'm less use to segue. You don't want to go back you want to dismiss your modal presentation.
  • Jason Rogers
    Jason Rogers about 12 years
    Not linked to the question but thanks, I've been looking for the pop function for a while but hadn't found the navigation controller (was looking in parent controller... Now it all makes cense
  • pAkY88
    pAkY88 over 11 years
    A little remark: if you want to go back to the previous view, without passing it as parameter, you can just use the following code: [[self navigationController] popViewControllerAnimated:YES];
  • joker
    joker over 9 years
    The comment made me try [self.navigationController.navigationController popToRootViewControllerAnimated:YES];. The structure was like: Navigation Controller -> TableView -> (via push segue) -> Navigation Controller -> View Controller. This worked with me! Moreover, it gave me insight of how things work.