skylerl
skylerl

Reputation: 4180

'Tried to pop to a view controller that doesn't exist.'

I am getting this error when I call my method dismissView. Here is the method stub:

-(IBAction)dismissView
{
    RootViewController *rootController = [[RootViewController alloc] initWithNibName:@"RootViewController" bundle:nil];
    [self.navigationController popToViewController:rootController animated:YES];
}

That should work, and I've checked, rootController is initialized and allocated. Any ideas?

Upvotes: 16

Views: 24043

Answers (11)

Denis Kutlubaev
Denis Kutlubaev

Reputation: 16124

Before popToViewController, check that NavigationController contains your ViewController:

if navigationController.viewControllers.contains(entryViewController) {
    navigationController.popToViewController(entryViewController, animated: true)
}

Upvotes: 0

Chris Tsitsaris
Chris Tsitsaris

Reputation: 600

Swift 4

For anyone still looking for a better solution that doesn't involve the UINavigationController stack indexes, which is getting more problematic with bigger navigation stack - here's the easiest way to solve this:

if let destinationViewController = navigationController?.viewControllers
                                                        .filter(
                                      {$0 is DestinationViewController})
                                                        .first {
    navigationController?.popToViewController(destinationViewController, animated: true)
}

Upvotes: 8

Arjun Patel
Arjun Patel

Reputation: 1510

self.navigationController?.present(viewControllers, animated: true, completion: nil)

Upvotes: -1

Guilherme Carvalho
Guilherme Carvalho

Reputation: 330

In my case the problem was that I was in the root ViewController and this works only for VCs that are stacked over it. To pop to the RootViewController use

navigationController?.popToRootViewController(animated: true)

Upvotes: 0

Rajesh Loganathan
Rajesh Loganathan

Reputation: 11217

Try this one line solution.

Swift 4+:

self.navigationController?.popToViewController ((self.navigationController?.viewControllers[1]) as! Your_ViewController, animated: true)

Objective-C:

[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];

Upvotes: 0

Krishna Shanbhag
Krishna Shanbhag

Reputation: 1517

The UINavigationController has a stack of ViewControllers which is stored in the viewControllers(NSArray) property. Enumerate to the required ViewController and pop to that ViewController.

Following code should solve the problem.

-(IBAction)dismissView
{
    NSArray *array = self.navigationController.viewControllers;
    for (id controller in array) {
        if ([controller isKindOfClass:[RootViewController class]]) {
            [self.navigationController popToViewController:controller animated:YES];

        }
    }
}

Upvotes: 1

Ben Gottlieb
Ben Gottlieb

Reputation: 85532

The -popToViewController is used to pop view controllers OFF the stack, down to one that already exists. Your UINavigationController has a stack of ViewControllers (stored in the viewControllers property), when you popToViewController, you're going to want to pass one of the elements in that array as the first argument.

What you most likely want to do in this case is use -popViewControllerAnimated:, which will remove the top ViewController from the stack

Upvotes: 13

Islam
Islam

Reputation: 3733

When using Push Segues you can easily go back to the root using this method:

[self.navigationController popToRootViewControllerAnimated:YES];

When using Modal Segues (because of the word dismiss in the question and as a general reference) you can dismiss the view controller using this method:

[self dismissViewControllerAnimated:YES completion:nil];

Upvotes: 1

Sergey Demchenko
Sergey Demchenko

Reputation: 2954

If you are using Storyboads, use this segue:

#import "PopToControllerSegue.h"

@implementation PopToControllerSegue

- (void) perform
{
    UIViewController *sourceViewController = (UIViewController *)self.sourceViewController;
    UIViewController *destinationViewController = (UIViewController *)self.destinationViewController;

    for (UIViewController* controller in sourceViewController.navigationController.viewControllers) {
        if ([controller isKindOfClass:destinationViewController.class]) {
            [sourceViewController.navigationController popToViewController:controller animated:YES];
            return;
        }
    }

    NSLog(@"PopToControllerSegue has failed!");
}

@end

Upvotes: 4

Joao Henrique
Joao Henrique

Reputation: 587

I had this problem recently and solved with something like this...

[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];

Upvotes: 28

Chuck
Chuck

Reputation: 237060

You're allocating the RootViewController right there. It does not exist in the navigation controller's stack, so no matter how far you pop, you won't reach it.

Upvotes: 6

Related Questions