ios8 uistoryboard uistoryboardsegue

ios8 - Cómo usar descartar un popover de iPhone en un guión gráfico adaptable



uistoryboard uistoryboardsegue (5)

Soy nuevo en el desarrollo de iOS, y estoy tratando de aprender storyboard, Swift y las nuevas características de iOS 8 al mismo tiempo.

He creado un guión gráfico muy simple que usa una secuencia de presentación Popover para mostrar otra vista. En el simulador, si ejecuto esto para un iPad, funciona como se esperaba. Sin embargo, si lo ejecuto para un iPhone, en lugar de un popover, muestra una vista de pantalla completa, en la parte superior de la vista original. Esto esta bien; sin embargo, no hay forma de descartarlo y volver a la pantalla original.

He visto el video WWDC 2014 "228 Una mirada dentro de los controladores de presentación" y pueden mostrar un botón de descartar si construyen la interfaz de usuario completamente con código.

También he visto la sesión "411 Novedades en el creador de interfaces", donde dicen que esto se puede hacer en Interface Builder, pero no lo muestran, y prometen mostrar cómo hacerlo en el laboratorio, si a alguien le interesa. Lamentablemente, no asistí a la WWDC 2014, ni conozco a nadie que lo haya hecho. Mis búsquedas de Google tampoco me han devuelto nada útil.


Puede agregar el controlador de navegación de esta manera:

  • Configure su controlador de vista Popover como el controlador de vista raíz a un controlador de navegación.
  • Eliminar el segue de popover que está utilizando actualmente
  • Vuelva a conectar la transición del botón en el que está mostrando el popover al controlador de navegación. En iPad obtendrás un popover y en el iPhone obtendrás una presentación modal. Tanto el iPad como el iPhone mostrarán el controlador de navegación. Dependiendo de su caso de uso, esto puede o no ser algo que desee. Aquí hay una muestra en pantalla de cómo debería ser el guión gráfico.

Si realmente quieres que tu controlador de vista siempre sea un popover deja tu guión gráfico como está y agrega algo como esto a tu controlador de vista que presente el popover-

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"Your segue name"]) { UIViewController *yourViewController = segue.destinationViewController; yourViewController.modalPresentationStyle = UIModalPresentationPopover; UIPopoverPresentationController *popoverPresentationController = yourViewController.popoverPresentationController; popoverPresentationController.delegate = self; } }

El controlador de vista que presenta el popover también tendrá que responder a este método UIPopoverPresentationDelegate

- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller { return UIModalPresentationNone;//always popover. }

Por último, puede hacer lo siguiente para agregar solo el controlador de navegación a la presentación modal de su controlador de vista en el iPhone y dejar el popover en el iPad sin un controlador de navegación.

  • Deje su guión gráfico como está.
  • El lugar adecuado para inyectar el controlador de navegación es - (UIViewController *)presentationController:(UIPresentationController *)controller viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style . Para que se pueda UIPopoverPresentationController , debemos establecernos como delegados de UIPopoverPresentationController . Una vez más haremos esto en prepareForSegue:

    -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"Your segue name"]) { UIViewController *yourViewController = segue.destinationViewController; yourViewController.modalPresentationStyle = UIModalPresentationPopover; UIPopoverPresentationController *popoverPresentationController = yourViewController.popoverPresentationController; popoverPresentationController.delegate = self; } }

Entonces haremos esto en el método de delegado que mencioné anteriormente

-(UIViewController *)presentationController:(UIPresentationController *)controller viewControllerForAdaptivePresentationStyle:(UIModalPresentationStyle)style { UIViewController *presentedViewController = controller.presentedViewController; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:presentedViewController]; UIBarButtonItem *dismissButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonItemStyleDone target:self action:@selector(done:)]; presentedViewController.navigationItem.rightBarButtonItem = dismissButton; return navigationController; }

¡Buena suerte!


Si lo que quieres es un popover en tu iPad pero una hoja modal con un botón de cierre en tu iPhone, entonces puedes hacerlo sin crear un controlador de navegación adicional en el guión gráfico para el popover.

En el storyboard Xcode 6.3, simplemente conectas un controlador de vista y designas el segue como "Presente como Popover"

El código siguiente debe ir en el controlador de vista que se dirige al popover, no en el popover en sí:

Primero configura el delegado de popover:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if (segue.identifier == "myPopoverSegueName") { let vc = segue.destinationViewController vc.popoverPresentationController?.delegate = self return } }

Luego, agrega la extensión de delegado (debajo del código del controlador de visualización) y crea el botón de control de navegación / cierre sobre la marcha:

extension myViewController: UIPopoverPresentationControllerDelegate { func presentationController(controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController? { let btnDone = UIBarButtonItem(title: "Done", style: .Done, target: self, action: "dismiss") let nav = UINavigationController(rootViewController: controller.presentedViewController) nav.topViewController.navigationItem.leftBarButtonItem = btnDone return nav } }

Luego agrega su función de descarte y debería estar listo para continuar:

func dismiss() { self.dismissViewControllerAnimated(true, completion: nil) }


No estoy seguro de por qué necesita configurar el guión gráfico para el botón Hecho, todo el trabajo se puede realizar mediante programación con pocas líneas de código. La parte importante es implementar algunos métodos de protocolo UIAdaptivePresentationControllerDelegate exactamente como a continuación:

func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle { return .FullScreen } func presentationController(controller: UIPresentationController, viewControllerForAdaptivePresentationStyle style: UIModalPresentationStyle) -> UIViewController?{ var navController:UINavigationController = UINavigationController(rootViewController: controller.presentedViewController) controller.presentedViewController.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action:"done") return navController }

Luego, un método simple para implementar el comportamiento de descarte para el popover en caso de que se presentara en pantalla completa:

func done (){ presentedViewController?.dismissViewControllerAnimated(true, completion: nil) }

y listo!


Es posible hacerlo con código mimimal mientras se pone la lógica en el guión gráfico. En el controlador de vista que presenta el popover, solo ingrese el método marcador

@IBAction func unwindToContainerVC(segue: UIStoryboardSegue) { }

No necesita ningún código, pero necesita estar presente para que pueda controlar el arrastre al ícono de Salir más adelante cuando usa el constructor de interfaz.

Tengo mi contenido de popover que no ocupa toda la vista de fondo, pero tiene un pequeño margen alrededor. Esto significa que puede usar el constructor de interfaz para crear un reconocedor de gestos de toque para esta vista. Controle arrastre el reconocedor de gestos al ícono Salir, que luego muestra algunas opciones de Salida, una de las cuales es el método unwindToContainerVC como se ve arriba.

Ahora cualquier toque alrededor del borde (como en un escenario de iPhone 4S) lo lleva de vuelta al controlador de vista que se presenta.

Aquí está el inspector de conexiones para el reconocedor de gestos:


En mi caso, tenía una pequeña ventana emergente que quería ser una ventana emergente tanto en un iPhone como en un iPad, y quería evitar el uso de una barra de navegación con un Descartar. Descubrió que se necesitaba implementar dos llamadas de delegado (Swift 3.0):

extension MyViewController : UIPopoverPresentationControllerDelegate { // Needed for iPhone popup func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle { return .none } // Needed for iPhone in landscape func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle { return .none } }