How do I pop two views at once from a navigation controller?
IosIphoneUinavigationcontrollerIos Problem Overview
I want to pop to the third view on the navigation stack back to the first view.
I know how to pop one view at once:
[self.navigationController popViewControllerAnimated:YES];
But how do I do two at once?
Ios Solutions
Solution 1 - Ios
You can try this to Jump between the navigation controller stack as well
NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
for (UIViewController *aViewController in allViewControllers) {
if ([aViewController isKindOfClass:[RequiredViewController class]]) {
[self.navigationController popToViewController:aViewController animated:NO];
}
}
Solution 2 - Ios
Here are two UINavigationController
extensions that can solve your problem. I would recommend using the first one that pops to a UIViewController
of a specific class:
extension UINavigationController {
func popToViewController(ofClass: AnyClass, animated: Bool = true) {
if let vc = viewControllers.filter({$0.isKind(of: ofClass)}).last {
popToViewController(vc, animated: animated)
}
}
func popViewControllers(viewsToPop: Int, animated: Bool = true) {
if viewControllers.count > viewsToPop {
let vc = viewControllers[viewControllers.count - viewsToPop - 1]
popToViewController(vc, animated: animated)
}
}
}
and use it like this:
// pop to SomeViewController class
navigationController?.popToViewController(ofClass: SomeViewController.self)
// pop 2 view controllers
navigationController?.popViewControllers(viewsToPop: 2)
Solution 3 - Ios
You can pop to the "root" (first) view controller with popToRootViewControllerAnimated
:
[self.navigationController popToRootViewControllerAnimated:YES];
// If you want to know what view controllers were popd:
// NSArray *popdViewControllers = [self.navigationController popToRootViewControllerAnimated:YES];
UINavigationController
Reference:
> Pops all the view controllers on the stack except the root view controller and updates the display.
>
> Return Value
> An array of view controllers that are popped from the stack.
Solution 4 - Ios
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
objectAtIndex:1 --> you can pass whichever index you want to pop to
Solution 5 - Ios
Swift 2 - xCode 7.3
This could be a very useful extension to pop UIViewControllers:
extension UINavigationController {
func popToViewControllerOfType(classForCoder: AnyClass) {
for controller in viewControllers {
if controller.classForCoder == classForCoder {
popToViewController(controller, animated: true)
break
}
}
}
func popViewControllers(controllersToPop: Int, animated: Bool) {
if viewControllers.count > controllersToPop {
popToViewController(viewControllers[viewControllers.count - (controllersToPop + 1)], animated: animated)
} else {
print("Trying to pop \(controllersToPop) view controllers but navigation controller contains only \(viewControllers.count) controllers in stack")
}
}
}
Solution 6 - Ios
If you just want to pop 2 at once because your rootViewController is (way) 'deeper' then 2 you could consider adding a category to UIviewController for example:
UINavigationController+popTwice.h
#import <UIKit/UIKit.h>
@interface UINavigationController (popTwice)
- (void) popTwoViewControllersAnimated:(BOOL)animated;
@end
UINavigationController+popTwice.m
#import "UINavigationController+popTwice.h"
@implementation UINavigationController (popTwice)
- (void) popTwoViewControllersAnimated:(BOOL)animated{
[self popViewControllerAnimated:NO];
[self popViewControllerAnimated:animated];
}
@end
Import the category #import "UINavigationController+popTwice.h"
somewhere in your implementation and use this line of code to pop 2 controllers at once:
[self.navigationController popTwoViewControllersAnimated:YES];
isn't that great? :)
Solution 7 - Ios
> Swift 4 :
func popViewControllerss(popViews: Int, animated: Bool = true) {
if self.navigationController!.viewControllers.count > popViews
{
let vc = self.navigationController!.viewControllers[self.navigationController!.viewControllers.count - popViews - 1]
self.navigationController?.popToViewController(vc, animated: animated)
}
}
Then Use This Method
self.popViewControllerss(popViews: 2)
Solution 8 - Ios
You can also try this one :-
[self.navigationController popToViewController:yourViewController animated:YES];
Solution 9 - Ios
//viewIndex = 1;
//viewIndex = 2;
//viewIndex = 3;
// **[viewControllers objectAtIndex: *put here your viewindex number*]
NSArray *viewControllers = [self.navigationController viewControllers];
[self.navigationController popToViewController:[viewControllers objectAtIndex:viewIndex] animated:NO];
Solution 10 - Ios
NSMutableArray *newStack = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
[newStack removeLastObject];
[newStack removeLastObject];
[self.navigationController setViewControllers:newStack animated:YES];
Solution 11 - Ios
In Swift 3, you can pop one, two or more viewcontrollers from navigation controller like that
let viewControllers = self.navigationController!.viewControllers as [UIViewController]
for aViewController:UIViewController in viewControllers {
if aViewController.isKind(of: FromWhereYouWantToGoController.self) {
_ = self.navigationController?.popToViewController(aViewController, animated: true)
}
}
Here FromWhereYouWantToGoController is destination controller. Hope it helps.
Solution 12 - Ios
You can pass the initial view controller (the one you want to come back to) and then call this line in the last view:
[self.navigationController popToViewController:yourInitialViewController animated:YES];
L.
Solution 13 - Ios
I didn't see this answer in here. If you only want to pop a few (not all the way to the root), you can just iterate through self.navigationController.viewControllers checking for class types, or if you have a reference use that:
for (UIViewController *aViewController in self.navigationController.viewControllers) {
if ([aViewController isKindOfClass:[SMThumbnailViewController class]]) {
[self.navigationController popToViewController:aViewController animated:YES];
}
}
Solution 14 - Ios
you can pop back to the root view controller
[self.navigationController popToRootViewControllerAnimated:YES];
or, if the view you want to pop to isn't the first one, you'll need to pop again in your previous view's viewWillAppear
Solution 15 - Ios
Here's a little function I'm using to go back X ViewControllers:
-(void)backMultiple:(id)data {
int back = 2; //Default to go back 2
int count = [self.navigationController.viewControllers count];
if(data[@"count"]) back = [data[@"count"] intValue];
//If we want to go back more than those that actually exist, just go to the root
if(back+1 > count) {
[self.navigationController popToRootViewControllerAnimated:YES];
}
//Otherwise go back X ViewControllers
else {
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:count-(back+1)] animated:YES];
}
}
Solution 16 - Ios
Swift Version as of (Swift 1.2 / Xcode 6.3.1) of popping twice or more
var viewControllers = self.navigationController?.viewControllers
viewControllers?.removeLast()
viewControllers?.removeLast()
self.navigationController?.setViewControllers(viewControllers, animated: true)
or
var viewControllers = self.navigationController?.viewControllers
var viewsToPop = 2
var end = (viewControllers?.count)!
var start = end - viewsToPop
viewControllers?.removeRange(Range<Int>(start: start, end: end))
self.navigationController?.setViewControllers(viewControllers, animated: true)
Solution 17 - Ios
**You can use the stack of the UIViewControllers.
-
Fetch the array of all the viewControllers in the stack.
-
Iterate through the whole array and find the desired viewController
by matching the class type. -
Pop the viewController.**
func popToSpecificViewC { let viewControllers: [UIViewController] = self.navigationController!.viewControllers as [UIViewController]; for viewController:UIViewController in viewControllers { if viewController.isKind(of: WelcomeViewC.self) { _ = self.navigationController?.popToViewController(viewController, animated: true) } } }
Solution 18 - Ios
Using a simple UINavigationController extension:
extension UINavigationController {
func popViewControllers(_ count: Int) {
guard viewControllers.count > count else { return }
popToViewController(viewControllers[viewControllers.count - count - 1], animated: true)
}
}