"L'application a essayé de présenter modalement un contrôleur actif"?

100

Je viens de tomber sur un crash montrant un NSInvalidArgumentExceptionavec ce message sur une application qui ne le faisait pas auparavant.

L'application a tenté de présenter modalement un contrôleur actif UITabBarController: 0x83d7f00.

J'ai un UITabBarControllerque je crée dans le AppDelegateet lui donne le tableau de UIViewControllers.

L'un d'entre eux que je souhaite présenter de manière modale lorsque j'appuie dessus. Je l'ai fait en implémentant la méthode des délégués

- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController

Si ce contrôleur de vue est de la classe de celui que je veux présenter modalement, je retourne NON et fais

[tabBarController presentModalViewController:viewController animated:YES];

Et maintenant, j'obtiens cette erreur, ce qui semble signifier que vous ne pouvez pas présenter modalement un contrôleur de vue qui est actif ailleurs (dans la barre d'onglets ...) Je devrais dire que je suis sur XCode 4.2 Developer Preview 7, donc c'est iOS 5 (je connais la NDA, mais je pense que je ne donne aucun détail interdit). Je n'ai actuellement pas d'installation XCode pour tester si cela plante la compilation avec le SDK iOS4, mais je suis presque entièrement sûr que ce n'est pas le cas.

Je voulais seulement demander si quelqu'un a rencontré ce problème ou a des suggestions

Javier Soto
la source
Avant iOS 5, cela ne soulevait pas d'exception, mais ne renvoyait rien. À partir d'iOS 5, cette commande lève une exception.
Frédéric Adda

Réponses:

103

Supposons que vous ayez trois contrôleurs de vue instanciés comme ceci:

UIViewController* vc1 = [[UIViewController alloc] init];
UIViewController* vc2 = [[UIViewController alloc] init];
UIViewController* vc3 = [[UIViewController alloc] init];

Vous les avez ajoutés à une barre d'onglets comme celle-ci:

UITabBarController* tabBarController = [[UITabBarController alloc] init];
[tabBarController setViewControllers:[NSArray arrayWithObjects:vc1, vc2, vc3, nil]];

Maintenant, vous essayez de faire quelque chose comme ceci:

[tabBarController presentModalViewController:vc3];

Cela vous donnera une erreur car ce contrôleur de barre d'onglets a une emprise mortelle sur le contrôleur de vue que vous lui avez donné. Vous pouvez soit ne pas l'ajouter au tableau des contrôleurs de vue dans la barre d'onglets, soit ne pas le présenter de manière modale.

Apple attend de vous que vous traitiez leurs éléments d'interface utilisateur d'une certaine manière. Ceci est probablement enterré quelque part dans les Directives de l'Interface Humaine comme un "ne faites pas cela parce que nous ne nous attendons pas à ce que vous vouliez jamais faire cela".

lswank
la source
6
Le fait est que ce n'était absolument aucun problème avant iOS 5, d'où mon inquiétude! Ce que j'ai fait a été d'ajouter un UIViewController factice à la barre d'onglets et de présenter de manière modale l'instance de sous-classe de contrôleur de vue réelle.
Javier Soto le
1
@Iswank, maintenant dans iOS 6, pour rendre les choses «plus faciles», ils ont désapprouvé presentModalViewController causant toutes sortes de problèmes de rotation ... vous devez utiliser presentViewController: animé: achèvement et vérifier comment votre application gère les changements
pourquoi
15

J'ai le même problème. J'essaie de présenter le contrôleur de vue juste après avoir rejeté.

[self dismissModalViewControllerAnimated:YES];

Quand j'essaie de le faire sans animation, cela fonctionne parfaitement, donc le problème est que le contrôleur est toujours en vie. Je pense que la meilleure solution est d'utiliser dismissViewControllerAnimated:completion:pour iOS5

Danil
la source
Il échoue si vous le rejetez, car au moment où vous souhaitez présenter à nouveau le contrôleur de vue modale, il est toujours modal à l'écran, en cours d'animation.
Pascal
2
Il est déprécié dans IOS 6.0
Sumit Kumar Saha
12

Dans mon cas, j'essayais de présenter le viewController (j'ai la référence du viewController dans le TabBarViewController) à partir de différents contrôleurs de vue et il plantait avec le message ci-dessus. Dans ce cas, pour éviter de présenter, vous pouvez utiliser

viewController.isBeingPresented

!viewController.isBeingPresented {
          // Present your ViewController only if its not present to the user currently.
}

Pourrait aider quelqu'un.

Karthick Ramesh
la source
il ne fonctionne que dans viewWillappperar mais quand je l'ai vérifié avant de présenter viewController qui est déjà présenté, il retourne toujours false.
guru
1
Ne travaille pas pour moi. Obtient toujours un plantage de l'application. (! viewController.presentingViewController) a résolu le problème.
Argus
3

J'ai eu le même problème, je le résous. Vous pouvez essayer ce code:

[tabBarController setSelectedIndex:1];
[self dismissModalViewControllerAnimated:YES];
Erhan Demirci
la source
2

La même erreur de problème m'est arrivée lorsque j'ai essayé presentun contrôleur de vue enfant au lieu de son UINavigationViewControllerparent

Nik
la source
0

Retirez simplement

[tabBarController presentModalViewController:viewController animated:YES];

et garde

[self dismissModalViewControllerAnimated:YES];
user170317
la source
cela donne un avertissement obsolète ... alors qu'est-ce qu'une alternative à cela?
Kirtikumar A.
Ici, j'ai utilisé [blockSelf licenciementViewControllerAnimated: OUI complétion: nil];
Kirtikumar A.
0

À la place d'utiliser:

self.present(viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Void)?)

vous pouvez utiliser:

self.navigationController?.pushViewController(viewController: UIViewController, animated: Bool)
Wimukthi Rajapaksha
la source
0

Dans mon cas, je présentais le rootViewControllerd'un UINavigationControllerquand j'étais censé présenter le UINavigationControllerlui - même.

Laura Corssac
la source