web-dev-qa-db-fra.com

Présentation modulaire d'un contrôleur de vue à partir d'un délégué d'une feuille d'action dans iOS8 - iOS11

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...>
58
Leo Natan

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];
});
138
Leo Natan

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.

31
Kjuly

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

enter image description here

4
Achille

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

Je l'ai corrigé dans Swift 3 avec le code suivant

  DispatchQueue.main.async {
            self.present(alertController, animated: true, completion: nil)
        }
2
Joan Cardona

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 :))

1
zurakach

É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.

1
Salvador

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.

0
Pankaj purohit

Essayer

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    // action sheet presentation
    // or modal view controller presentation
    // or alert view presentation
}];
0
Tim