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

J’utilise une application basée sur la navigation. Je pousse First ViewController à Second ViewController et de Second ViewController à Third ViewController. Maintenant, je veux passer de Third ViewController à First ViewController. J’effectue cette tâche en utilisant le code ci-dessous, mais mon application est tombée en panne.

S’il vous plaît n’importe quel corps me donne des directives appropriées. Je ne peux pas utiliser pop pour rootViewController parce que c’est différent viewController. Merci d’avance…

Dans Third ViewControler, j’ai écrit ceci:

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

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]; 

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

Façon Swifty:

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

Il est souvent plus important de le faire depuis le haut de la stack, 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]; 
 - (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; } } } 

Version rapide et sûre de Swift 3 :

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

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

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

Si vous revenez à une distance connue, vous pouvez appeler popViewControllerAnimated: plus d’une fois. Dans votre exemple, ce serait 2 contrôleurs pour les appels. Vous pouvez faire la même chose en regardant dans viewControllers pour le contrôleur 2 à partir de la fin et en y viewControllers .

Les suggestions ci-dessus sont des solutions rapides. Un scénario de meilleure pratique serait de passer le contrôleur sur lequel vous voulez revenir à chaque contrôleur successif que vous poussez. Se passe d’abord à la seconde, la seconde passe cette référence à la troisième, la troisième à la référence passée, qui est la première.

En fait, vous créez un contrôleur racine temporaire. Vous pouvez sous- UINavigationController et append une propriété temporaryRoot et une méthode popToTemporaryRootViewControllerAnimated: qui apparaîtra dans votre racine temporaire et la supprimera. Quand il pousse les secondes pour la première fois, il se définit également comme racine temporaire afin que chaque contrôleur de la stack ne soit pas obligé de passer une référence. Vous devrez append des vérifications supplémentaires pour vous assurer que vous ne dépasserez jamais le temporaireRoot sans le supprimer.

Après beaucoup d’efforts, quelqu’un a créé une extension rapide vers 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 } } } } 

Appel de méthode:

  self.navigationController?.backToViewController(viewController: YourViewController.self) 

Mis en œuvre et testé dans Swift 3.0

Vous trouverez ci-dessous une méthode qui peut être utile pour naviguer dans 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) 

Je pense que .filter({...}).first Est d’ .filter({...}).first un peu plus lent que .first(where: {...}) . De plus, cela pourrait être écrit plus précisément pour ne traiter que les UIViewControllers.

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

Mis à jour pour Swift 3:

utilisé en dessous du code simple, pour la commande pop à un 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 } } 
 for controller in self.navigationController!.viewControllers as Array { if controller.isKind(of: LoginVC.self) { _ = self.navigationController!.popToViewController(controller, animated: true) break } } 

Mettez la fonction dans UIViewController 1. Elle vérifie si UIViewController spécifique existe dans UINavigationController puis dans popToViewController ou si 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) 

Version rapide 4

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