J'ai donc remarqué que dans iOS8 beta 3 (Mise à jour: il se produit encore dans iOS 11.2) sur iPad, lors de la tentative de présentation d'un contrôleur de vue à partir de la méthode de délégation d'un UIActionSheet
, "rien "se produit et un message de journal est envoyé à la console de débogage, indiquant que la présentation a été tentée lors de la transition d’un contrôleur d’alertes:
Warning: Attempt to present <UIViewController: 0x...> on <ViewController: 0x...> which is already presenting <UIAlertController: 0x...>
Mise à jour: À partir du SDK iOS 9, UIActionSheet
est obsolète. Ne vous attendez donc pas à un correctif concernant ce problème. Il est préférable de commencer à utiliser UIAlertController
lorsque cela est possible.
Le problème semble venir du passage d'Apple à utiliser UIAlertController
en interne pour implémenter la fonctionnalité des vues d'alerte et des feuilles d'action. Le problème se pose principalement sur l'iPad et les feuilles d'action, car sur l'iPad, les feuilles d'action sont présentées sous forme de popover dans une vue spécifiée et ce que Apple parcourt la chaîne de répondeurs jusqu'à ce qu'il trouve un contrôleur de vue et appelle presentViewController:animated:completion:
Avec le UIAlertController
interne. Le problème est moins évident sur les iPhone et les vues d’alerte, car Apple crée en fait une fenêtre distincte, un contrôleur de vue vide et présente l’interne UIAlertController
en plus, de sorte qu’il ne semble pas interférer. avec une autre présentation.
J'ai ouvert un rapport de bogue pour ce problème: rdar: // 17742017. Veuillez le dupliquer et informer Apple que c'est un problème.
En guise de solution de contournement, je vous recommande de retarder la présentation jusqu'à la prochaine boucle d'exécution, en utilisant la méthode suivante:
dispatch_async(dispatch_get_main_queue(), ^ {
[self presentViewController:vc animated:YES completion:nil];
});
Vous pouvez essayer de faire votre travail (présentation du contrôleur de vue) dans
- (void) actionSheet:(UIActionSheet *)actionSheet
didDismissWithButtonIndex:(NSInteger)buttonIndex {}
au lieu de
- (void) actionSheet:(UIActionSheet *)actionSheet
clickedButtonAtIndex:(NSInteger)buttonIndex {}
comme @LeoNatan l'a dit, "Le problème semble venir du passage d'Apple à utiliser UIAlertController en interne pour implémenter les fonctionnalités des vues d'alerte et des feuilles d'action". Vous devez donc attendre que la fiche d’action soit rejetée, puis présenter le contrôleur de vue souhaité.
La solution de @ LeoNatan bloque simplement l'interface utilisateur au niveau du thread principal. Elle s'assure également que le contrôleur de vue sera présenté après le rejet de la fiche d'action.
malheureusement, ce code ne fonctionne pas pour moi, je pense que mon problème n’appelait pas la méthode presentController directement, mais dans la méthode prepareForSegue.
[segue destinationViewController]
J'ai remarqué que si le genre est "Push", tout fonctionne correctement, mais s'il est "modal", sur ipad, j'ai cette erreur.
Ensuite, j'ai trouvé une nouvelle option dans le storyboard dans le panneau de division, et j'ai résolu mon problème en choisissant "Contexte actuel" pour l'option Présentation.
J'espère que cela sera utile pour quelqu'un d'autre ... voici la capture d'écran de l'option
J'ai eu le même problème. J'ai créé une fenêtre séparée pour les alertes et les feuilles d'action dans mon appdelegate et j'ai présenté les alertes. Cela a fonctionné pour moi!
self.alertWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.alertWindow.backgroundColor = [UIColor clearColor];
UIViewController *dummy = [[UIViewController alloc] init];
[self.alertWindow setRootViewController:dummy];
Vous pouvez présenter comme:
[[myAppDelegate appDelegate].alertWindow makeKeyAndVisible];
[[myAppDelegate appDelegate].alertWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
Je l'ai corrigé dans Swift 3 avec le code suivant
DispatchQueue.main.async {
self.present(alertController, animated: true, completion: nil)
}
utilisation
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
au lieu de
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
La vue d'action est présentée au-dessus de l'actuelle current VC), ce qui cause l'avertissement/l'erreur. Lorsque didDismiss est appelé, la vue d'action est déjà rejetée, donc aucun problème :))
Émettre un
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
sur
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
avant d'essayer de présenter une autre vue modale a fonctionné pour moi.
Dans iOS 8 Apple utilise UIAlertController en interne pour implémenter les fonctionnalités des vues d'alerte et des feuilles d'action. Ainsi, lorsque vous souhaitez afficher un UIViewController de manière modale après avoir affiché UIActionSheet ou UIAlertView dans une méthode déléguée, comme
(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
et
(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
vous devez d'abord rejeter UIAlertController comme suit:
if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0"))
{
UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
[vc dismissViewControllerAnimated:NO completion:^{
}];
}
Vous pouvez maintenant présenter un UIViewController modal dans iOS 8.
Essayer
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
// action sheet presentation
// or modal view controller presentation
// or alert view presentation
}];