web-dev-qa-db-fra.com

Comment extraire deux vues à la fois d'un contrôleur de navigation?

Je souhaite passer à la troisième vue de la pile de navigation et revenir à la première vue.

Je sais comment afficher une vue à la fois:

[self.navigationController popViewControllerAnimated:YES];

Mais comment puis-je faire deux à la fois?

Merci...

80
Adam Waite

Vous pouvez aussi essayer cela entre la pile du contrôleur de navigation

NSMutableArray *allViewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
for (UIViewController *aViewController in allViewControllers) {
    if ([aViewController isKindOfClass:[RequiredViewController class]]) {
        [self.navigationController popToViewController:aViewController animated:NO];
    }
}
123
Meet

Voici deux extensions UINavigationController qui peuvent résoudre votre problème. Je recommanderais d'utiliser le premier qui apparaît sur un UIViewController d'une classe spécifique

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)
    }
  }

}

et l'utiliser comme ça:

// pop to SomeViewController class
navigationController?.popToViewController(ofClass: SomeViewController.self)

// pop 2 view controllers
navigationController?.popViewControllers(viewsToPop: 2)
51
budidino

Vous pouvez accéder au contrôleur de vue "racine" (premier) avec popToRootViewControllerAnimated:

[self.navigationController popToRootViewControllerAnimated:YES];

// If you want to know what view controllers were popd:
// NSArray *popdViewControllers = [self.navigationController popToRootViewControllerAnimated:YES];

UINavigationController Référence :

Dépose tous les contrôleurs de vue de la pile sauf le contrôleur de vue racine et met à jour l'affichage.

Valeur de retour
Tableau de contrôleurs de vue extraits de la pile.

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

objectAtIndex: 1 -> vous pouvez transmettre l'index que vous souhaitez afficher

29
Zaraki

Swift 2 - xCode 7.3

Cela pourrait être une extension très utile pour faire apparaître 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")
        }
    }
}
18
lubilis

Si vous voulez juste faire apparaître 2 immédiatement parce que votre rootViewController est (plus) profond, alors vous pouvez envisager d'ajouter une catégorie à UIviewController par exemple: 

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

Importez la catégorie #import "UINavigationController+popTwice.h" quelque part dans votre implémentation et utilisez cette ligne de code pour faire apparaître 2 contrôleurs à la fois:

[self.navigationController popTwoViewControllersAnimated:YES];

n'est-ce pas génial? :)

15
Tieme
//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];
5
Sabareesh

Vous pouvez aussi essayer celui-ci: - 

[self.navigationController popToViewController:yourViewController animated:YES];
5
Leena
    NSMutableArray *newStack = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
    [newStack removeLastObject];
    [newStack removeLastObject];
    [self.navigationController setViewControllers:newStack animated:YES];
4
patrickandroid

Dans Swift 3 , Vous pouvez extraire un, deux ou plusieurs contrôleurs de vue du contrôleur de navigation comme ça

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 est un contrôleur de destination. J'espère que ça aide. 

4
Riajur Rahman

Vous pouvez passer le contrôleur de vue initial (celui auquel vous voulez revenir) puis appeler cette ligne dans la dernière vue:

[self.navigationController popToViewController:yourInitialViewController animated:YES];

L.

3
Lucas

Je n'ai pas vu cette réponse ici. Si vous souhaitez seulement en afficher quelques-uns (pas complètement à la racine), vous pouvez simplement effectuer une itération via self.navigationController.viewControllers en recherchant les types de classe, ou si vous avez une référence, utilisez ceci:

for (UIViewController *aViewController in self.navigationController.viewControllers) {
   if ([aViewController isKindOfClass:[SMThumbnailViewController class]]) {
      [self.navigationController popToViewController:aViewController animated:YES];
   }
}
3
VaporwareWolf

Voici une petite fonction que j'utilise pour revenir en arrière 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];
    }
}
2
Mark

vous pouvez revenir au contrôleur de vue racine

[self.navigationController popToRootViewControllerAnimated:YES];

ou, si la vue sur laquelle vous souhaitez passer n'est pas la première, vous devez la repasser dans la vue précédente de votre vue précédente.

2
Robotnik

Vous pouvez utiliser la pile de UIViewControllers . 1. Récupérez le tableau de tous les viewControllers de la pile . 2. Parcourez tout le tableau et trouvez le viewController souhaité
en faisant correspondre le type de classe . 3. Pop le 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)
            }
        }
}
1
Peeyush karnwal

Version Swift à partir de (Swift 1.2/Xcode 6.3.1) De apparaître deux fois ou plus

 var viewControllers = self.navigationController?.viewControllers
 viewControllers?.removeLast()
 viewControllers?.removeLast()
 self.navigationController?.setViewControllers(viewControllers, animated: true)

ou 

 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)
1
Glenn S

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)
    }
}

Puis utilisez cette méthode

self.popViewControllerss(popViews: 2)
0
Saifan Nadaf