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];
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 rapide:
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 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];
- (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;
}
}
}
Rapide et sûr Swift 3 version:
if let vc = navigationController.viewControllers.filter({ $0 is SpecificViewControllerClass }).first {
navigationController.popToViewController(vc, animated: true)
}
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)
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)
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)
}
}
}
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.
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
}
}
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 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)
}
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)
for controller in self.navigationController!.viewControllers as Array {
if controller.isKind(of: LoginVC.self) {
_ = self.navigationController!.popToViewController(controller, animated: true)
break
}
}