web-dev-qa-db-fra.com

Puis-je accéder à ViewController spécifique?

J'utilise une application basée sur la navigation. Je pousse First ViewController vers Second ViewController et de Second ViewController vers Third ViewController. Maintenant, je souhaite passer de Third ViewController à First ViewController. J'effectue cette tâche à l'aide du code ci-dessous, mais mon application s'est bloquée.

S'il vous plaît n'importe quel organisme me donner des directives appropriées. Je ne peux pas utiliser pop pour rootViewController car c'est un viewController différent. Merci d'avance...

Dans Third ViewControler j'ai écrit ceci:

FirstViewCtr *x=[[FirstViewCtr alloc] initWithNibName:@"FirstViewCtr" bundle:nil];
[self.navigationController popToViewController:x animated:NO];
46
Ankit Vyas

En écrivant la première ligne, vous obtenez les index de tous les contrôleurs de vue et à partir de la deuxième ligne, vous atteignez votre destination.

NSArray *array = [self.navigationController viewControllers];

[self.navigationController popToViewController:[array objectAtIndex:2] animated:YES];
90
Ankit Vyas

Une approche plus sûre:

- (void)turnBackToAnOldViewController{

    for (UIViewController *controller in self.navigationController.viewControllers) {

        //Do not forget to import AnOldViewController.h
        if ([controller isKindOfClass:[AnOldViewController class]]) { 

            [self.navigationController popToViewController:controller
                                                  animated:YES];
            return;
        }
    }
}
72
Yunus Nedim Mehel

Façon rapide:

     let dashboardVC = navigationController!.viewControllers.filter { $0 is YourViewController }.first!
     navigationController!.popToViewController(dashboardVC, animated: true)
12
SwiftGod
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
7
Vikash Kumar

Il est souvent plus important de faire cela du haut de la pile, donc:

- (void)popToLast:(Class)aClass
{
    for (int i=self.navigationController.viewControllers.count-1; i>=0; i--)
    {
        UIViewController *vc = self.navigationController.viewControllers[i];
        if ([vc isKindOfClass:aClass])
        {
            [self.navigationController popToViewController:vc animated:YES];
            break;
        }
    }
}

et vous appelez ça

popToLast:[SomeViewController class];
6
Leszek Zarna
- (void) RetunToSpecificViewController{

   for (UIViewController *controller in self.navigationController.viewControllers)
    {
           if ([controller isKindOfClass:[AnOldViewController class]])
           {
            //Do not forget to import AnOldViewController.h

                       [self.navigationController popToViewController:controller
                                                             animated:YES];
                        break;
            }
    }
}
5
Mahendra Y

Rapide et sûr Swift 3 version:

if let vc = navigationController.viewControllers.filter({ $0 is SpecificViewControllerClass }).first {
  navigationController.popToViewController(vc, animated: true)
}
2
budidino

Mis en œuvre et testé dans Swift 3.0  

Vous trouverez ci-dessous une méthode utile pour accéder à un contrôleur de vue spécifique:

func poptoSpecificVC(viewController : Swift.AnyClass){
        let viewControllers: [UIViewController] = self.navigationController!.viewControllers
        for aViewController in viewControllers {
            if aViewController.isKind(of: viewController) {
                self.navigationController!.popToViewController(aViewController, animated: true)
                break;
            }
        }
    }

Utilisation:

self.poptoSpecificVC(viewController: createIntervalVC.self)
1
Ketan P

Après de nombreux efforts, quelqu'un a créé l'extension Swift de revenir à un contrôleur de vue particulier dans Swift 3.0.

extension UINavigationController {

    func backToViewController(viewController: Swift.AnyClass) {

            for element in viewControllers as Array {
                if element.isKind(of: viewController) {
                    self.popToViewController(element, animated: true)
                break
            }
        }
    }
}

Méthode d'appel:

 self.navigationController?.backToViewController(viewController: YourViewController.self)
1
Ved Rauniyar

Je pense que .filter({...}).first est un peu plus lent que .first(where: {...}). Cela pourrait également être écrit plus précisément pour ne traiter que de UIViewControllers.

extension UINavigationController {
    func popToController<T: UIViewController>(_ type: T.Type, animated: Bool) {
        if let vc = viewControllers.first(where: { $0 is T }) {
            popToViewController(vc, animated: animated)
        }
    }
    func popToControllerOrToRootControllerIfNotInTheStack<T: UIViewController>(_ type: T.Type, animated: Bool) {
        if let vc = viewControllers.first(where: { $0 is T }) {
            popToViewController(vc, animated: animated)
        } else {
            popToRootViewController(animated: animated)
        }
    }
}
1

Votre code crée une nouvelle instance d'une vue qui n'a jamais été insérée dans la pile, puis tente de revenir à ce contrôleur.

Si vous revenez au contrôleur de vue racine, vous pouvez utiliser popToRootViewControllerAnimated:

Si vous parcourez une distance connue, vous pouvez appeler popViewControllerAnimated: plusieurs fois. Dans votre exemple, ce serait 2 contrôleurs donc des appels. Vous pouvez faire la même chose en regardant dans viewControllers pour le contrôleur 2 à partir de la fin et en sautant dessus.

Les suggestions ci-dessus sont des solutions rapides. Un scénario de meilleure pratique consiste à transmettre le contrôleur auquel vous souhaitez revenir à chaque contrôleur successif que vous appuyez. Le premier passe lui-même au second, le second passe cette référence au troisième, le troisième passe à la référence passée, qui est le premier.

En effet, vous créez un contrôleur racine temporaire. Vous pouvez sous-classer UINavigationController et ajouter une propriété temporaryRoot et une méthode popToTemporaryRootViewControllerAnimated: qui s'afficheraient dans votre racine temporaire et l'effaceraient. Lorsque vous appuyez pour la première fois sur quelques secondes, il se définit également comme racine temporaire, de sorte que tous les contrôleurs de la pile ne doivent pas transmettre de référence. Vous devrez ajouter des vérifications supplémentaires pour être sûr de ne jamais passer devant la racine temporaire sans l'effacer.

1
drawnonward

Mise à jour pour Swift 3:

utilisé sous le code simple, pour passer au contrôleur de vue spécifique;

 for vc in self.navigationController!.viewControllers as Array {
          if vc.isKind(of: YourViewControllerName) {
               self.navigationController!.popToViewController(vc, animated: true)
               break
          }
    }
1
Kiran jadhav

Swift 4 version 

if let viewController = navigationController?.viewControllers.first(where: {$0 is YourViewController}) {
      navigationController?.popToViewController(viewController, animated: false)
}

Vous pouvez spécifier un autre filtre sur .viewControllers.first selon vos besoins, par exemple, si vous avez le même kindde contrôleurs de vue résidant dans le contrôleur de navigation, vous pouvez spécifier une vérification supplémentaire comme ci-dessous

  if let viewController = navigationController?.viewControllers.first(where: {
        if let current = $0 as? YourViewController {
             return current.someProperty == "SOME VALUE"
        }
       return false } ) {
            navigationController?.popToViewController(viewController, animated: false)
   }
0
Umair

Mettez la fonction dans UIViewController 1. il vérifie si un UIViewController spécifique existe dans UINavigationController puis popToViewController ou alors pushViewController

func navigate(_ navVC: AnyClass, pushVC: UIViewController) {
    for obj in self.navigationController!.viewControllers {
        if obj.isMember(of: navVC) {
            self.navigationController!.popToViewController(obj, animated: true)
            return
        }
    }
    self.navigationController!.pushViewController(pushVC, animated: true)
}

Utilisation

self.navigate(ViewController.self, pushVC: self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController)
0
Harshad Pipaliya
for controller in self.navigationController!.viewControllers as Array {
        if controller.isKind(of: LoginVC.self) {
            _ =  self.navigationController!.popToViewController(controller, animated: true)
            break
        }
    }
0
Ankit Vyas