Presentación de un controlador de vista de manera modal desde el delegado de una hoja de acción en iOS8 – iOS11

Así que noté que en iOS8 beta 3 ( Actualización : aún ocurre en iOS 11.2) en iPad, cuando bash presentar un controlador de vista desde un método de delegado de una UIActionSheet de UIActionSheet , “no pasa nada” y se UIActionSheet un mensaje de registro a la consola de depuración , indicando que se intentó la presentación durante la transición de un controlador de alerta:

 Warning: Attempt to present  on  which is already presenting  

Actualización: A partir de iOS 9 SDK, UIActionSheet está en desuso, así que no esperes una solución con respecto a este problema. Lo mejor es comenzar a usar UIAlertController cuando sea posible.


El problema parece provenir del cambio de Apple al uso de UIAlertController internamente para implementar la funcionalidad de las vistas de alerta y las hojas de acción. El problema se ve principalmente en el iPad y en las hojas de acción, porque en el iPad, las hojas de acción se presentan como un popover dentro de una vista especificada, y lo que hace Apple es desplazarse por la cadena de respuestas hasta que encuentra un controlador de vista y llama a presentViewController:animated:completion: con el UIAlertController interno. El problema es menos obvio en iPhone y con vistas de alerta, porque Apple realmente crea una ventana separada, un controlador de vista vacío y presenta el UIAlertController interno UIAlertController de eso, por lo que parece no interferir con otras presentaciones.

He abierto el informe de error para este problema: rdar: // 17742017 . Por favor duplíquelo y deje que Apple sepa que esto es un problema.

Como solución alternativa, recomiendo retrasar la presentación hasta el siguiente ciclo de ejecución, utilizando el siguiente método:

 dispatch_async(dispatch_get_main_queue(), ^ { [self presentViewController:vc animated:YES completion:nil]; }); 

Puede intentar hacer su trabajo (presentando controlador de vista) en

 - (void) actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {} 

en lugar de

 - (void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {} 

como dijo @LeoNatan, “El problema parece provenir del cambio de Apple al uso de UIAlertController internamente para implementar la funcionalidad de las vistas de alerta y las hojas de acción” . Por lo tanto, debe esperar a que se descarte la hoja de acciones y luego presentar el controlador de vista que desea.

La solución de @ LeoNatan simplemente bloquea la interfaz de usuario en el hilo principal, por lo que también se asegurará de que se presente el controlador de vista una vez que se haya descartado la hoja de acción.

desafortunadamente este código no funciona para mí, creo que porque mi problema no era invocar el método presentController directamente, sino en el método prepareForSegue, por lo que usé

 [segue destinationViewController] 

Me he dado cuenta de que si el segue es de tipo “push”, todo funciona correctamente, pero si es “modal”, solo en ipad, obtuve ese error.

Luego encontré una nueva opción en el guión gráfico en el panel segue y soplé con mi problema al elegir “Contexto actual” para la opción Presentación

Espero que esto sea útil para otra persona … aquí está la captura de pantalla sobre la opción

enter image description here

Tuve el mismo problema. Creé una ventana separada para alertas y hojas de acciones en mi appdelegate y presenté las alertas en ella. ¡Funcionó para mí!

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

Puede presentar como:

 [[myAppDelegate appDelegate].alertWindow makeKeyAndVisible]; [[myAppDelegate appDelegate].alertWindow.rootViewController presentViewController:alertController animated:YES completion:nil]; 

Lo arreglé en Swift 3 con el siguiente código

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

Emisión de un

 [self.navigationController dismissViewControllerAnimated:YES completion:nil]; 

en

 - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 

antes de tratar de presentar otra vista modal funcionó para mí.

utilizar

 - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex 

en lugar de

 - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 

La vista de acción se presenta sobre el VC actual, por lo que es lo que causa la advertencia / error. cuando se llama a Didmiss, la vista de acción ya está descartada, por lo que no hay ningún problema :))

Tratar

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

En iOS 8, Apple usa UIAlertController internamente para implementar la funcionalidad de vistas de alerta y hojas de acción. Entonces, cuando quiera mostrar un UIViewController de manera modal después de mostrar UIActionSheet o UIAlertView en un método delegado como

 (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex 

y

 (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex 

primero debe descartar UIAlertController de la siguiente manera:

 if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) { UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; [vc dismissViewControllerAnimated:NO completion:^{ }]; } 

Ahora puede presentar un UIViewController modal en iOS 8.