¿Es posible determinar si ViewController se presenta como modal?

¿Es posible comprobar dentro de la class ViewController que se presenta como controller de vista modal?

Solutions Collecting From Web of "¿Es posible determinar si ViewController se presenta como modal?"

Como modalViewController ha quedado en desuso en iOS 6, aquí hay una versión que funciona para iOS 5+ y que comstack sin advertencias.

C objective:

 - (BOOL)isModal { return self.presentingViewController.presentedViewController == self || (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController) || [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]]; } 

Rápido:

 var isModal: Bool { return self.presentingViewController?.presentedViewController == self || (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController) || self.tabBarController?.presentingViewController is UITabBarController } 

Sombrero de punta a la respuesta de Felipe.

Si buscas iOS 6+, esta respuesta está en desuso y deberías consultar la respuesta de Gabriele Petronella


No hay una forma clara de hacerlo, como una propiedad o método nativo de UIKit. Lo que puede hacer es verificar varios aspectos de su controller para asegurarse de que se presenta como modal.

Por lo tanto, para comprobar si el controller actual (representado como self en el código siguiente) se presenta de forma modal o no, tengo la function debajo de una categoría UIViewController , o (si su proyecto no necesita usar otros controlleres UIKit , como UITableViewController por ejemplo) en un controller de base que mis otros controlleres henetworkingan de

 -(BOOL)isModal { BOOL isModal = ((self.parentViewController && self.parentViewController.modalViewController == self) || //or if I have a navigation controller, check if its parent modal view controller is self navigation controller ( self.navigationController && self.navigationController.parentViewController && self.navigationController.parentViewController.modalViewController == self.navigationController) || //or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation [[[self tabBarController] parentViewController] isKindOfClass:[UITabBarController class]]); //iOS 5+ if (!isModal && [self respondsToSelector:@selector(presentingViewController)]) { isModal = ((self.presentingViewController && self.presentingViewController.modalViewController == self) || //or if I have a navigation controller, check if its parent modal view controller is self navigation controller (self.navigationController && self.navigationController.presentingViewController && self.navigationController.presentingViewController.modalViewController == self.navigationController) || //or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation [[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]]); } return isModal; } 

EDIT: agregué la última comprobación para ver si se está utilizando un UITabBarController y presentas otro UITabBarController como modal.

EDIT 2: agrega la comprobación de iOS 5+, donde UIViewController ya no responde para parentViewController , sino que presentingViewController parentViewController en su lugar.

EDIT 3: He creado una esencia para ello en caso de https://gist.github.com/3174081

En iOS5 +, como puede ver en Referencia de class UIViewController , puede getlo desde la propiedad "presentingViewController".

presentingViewController El controller de vista que presentó este controller de vista. (solo lectura)

@property (nonatomic, readonly) UIViewController * presentingViewController
Discusión

Si el controller de vista que recibió este post lo presenta otro controller de vista, esta propiedad contiene el controller de vista que lo está presentando. Si no se presenta el controller de vista, pero se presenta uno de sus antepasados, esta propiedad mantiene al controller de vista que presenta el antepasado más cercano. Si ni el controller de vista ni ninguno de sus antepasados ​​se presentan, esta propiedad es nula.

Disponibilidad
Disponible en iOS 5.0 y posterior.
Declarado en
UIViewController.h

Si no es así, puede definir una propiedad para esto ( presentedAsModal ) en su subclass UIViewController y establecerla en YES antes de presentar ViewController como una vista modal.

 childVC.presentedAsModal = YES; [parentVC presentModalViewController:childVC animated:YES]; 

Puede verificar este valor en su viewWillAppear . viewWillAppear .

Creo que no hay una propiedad oficial que indique cómo se presenta la vista, pero nada le impide crear la suya.

La respuesta de Petronella no funciona si self.navigationController se presenta de manera modal, pero self no es igual a self.navigationController.viewControllers [0], en ese caso self es empujado.

Aquí es cómo puedes solucionar el problema.

 return self.presentingViewController.presentedViewController == self || (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController && self == self.navigationController.viewControllers[0]) || [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]]; 

Y en Swift:

 return self.presentingViewController?.presentedViewController == self || (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController && self.navigationController?.viewControllers[0] == self) || self.tabBarController?.presentingViewController is UITabBarController 

Esto debería funcionar.

 if(self.parentViewController.modalViewController == self)… 

La mejor forma de verificar

  if (self.navigationController.presentingViewController) { NSLog(@"Model Present"); } 

Si no necesita distinguir entre las vistas modales de pantalla completa y las vistas no modales, como es el caso en mi proyecto (estaba tratando con un problema que solo ocurre con las hojas de formulario y hojas de página), puede usar modalPresentationStyle propiedad de UIViewController:

 switch (self.modalPresentationStyle) { case 0: NSLog(@"full screen, or not modal"); break; case 1: NSLog(@"page sheet"); break; case 2: NSLog(@"form sheet"); break; } 

En Swift :

 func isUIViewControllerPresentedAsModal() -> Bool { if((self.presentingViewController) != nil) { return true } if(self.presentingViewController?.presentedViewController == self) { return true } if(self.navigationController?.presentingViewController?.presentedViewController == self.navigationController) { return true } if((self.tabBarController?.presentingViewController?.isKindOfClass(UITabBarController)) != nil) { return true } return false } 

En mi proyecto tengo un controller de vista (Detalle) que puede presentarse de manera modal (al agregar un nuevo elemento) o con push (al editar uno existente) por el controller de vista maestra. Cuando el usuario pulsa [Listo], el controller de vista de Detalle llama al método de controller de vista maestra para notificar que está listo para cerrarse. El maestro debe determinar cómo se presenta el detalle para saber cómo cerrarlo. Así es como hago esto:

 UIViewController *vc = self.navigationController.viewControllers.lastObject; if (vc == self) { [self dismissViewControllerAnimated:YES completion:NULL]; } else { [self.navigationController popViewControllerAnimated:YES]; } 

Un truco como este podría funcionar.

 UIViewController* child = self; UIViewController* parent = child.parentViewController; while (parent && parent.modalViewController != child) { child = parent; parent = child.parentViewController; } if (parent) { // A view controller in the hierarchy was presented as a modal view controller } 

Sin embargo, creo que mi respuesta anterior es una solución más limpia.

Lo que funcionó para mí es seguir:

 // this is the trick: set parent view controller as application's window root view controller UIApplication.shanetworkingApplication.delegate.window.rootViewController = viewController; // assert no modal view is presented XCTAssertNil(viewController.presentedViewController); // simulate button tap which shows modal view controller [viewController.deleteButton sendActionsForControlEvents:UIControlEventTouchUpInside]; // assert that modal view controller is presented XCTAssertEqualObjects(viewController.presentedViewController.class, MyModalViewController.class); 

Hasta donde lo probé, esto funciona para iOS7 y iOS8. No probé en iOS6 sin embargo.

He mirado un poco para encontrar la respuesta correcta a esta pregunta, y no pude encontrar ninguna que cubra todos los posibles escenarios. Escribí estas pocas líneas de código que parecen hacer el trabajo. Puede encontrar algunos comentarios en línea para averiguar qué ha sido verificado.

 - (BOOL)isModal { BOOL modal = NO; if ([self presentingViewController]) { //Some view Controller is presenting the current stack UIViewController *presented = [[self presentingViewController] presentedViewController]; // What's been presented if ([presented respondsToSelector:@selector(viewControllers)]) { // There's a stack NSArray *viewControllers = [presented performSelector:@selector(viewControllers)]; modal = [viewControllers firstObject] == self; // Current VC is presented modally if it's the first in the stack } else { modal = presented == self; // Don't think this is actually needed. set modal = YES should do the job tho. } } return modal; } 

Espero que esto ayude.

Aquí está mi versión modificada de @ GabrielePetronella's isModal , que funciona con los controlleres de vista contenidos, ya que primero sube a la jerarquía parentViewController. También sacó el código en varias líneas para que quede claro qué está haciendo.

 var isModal: Bool { // If we are a child view controller, we need to check our parent's presentation // rather than our own. So walk up the chain until we don't see any parentViewControllers var potentiallyPresentedViewController : UIViewController = self while (potentiallyPresentedViewController.parentViewController != nil) { potentiallyPresentedViewController = potentiallyPresentedViewController.parentViewController! } if self.presentingViewController?.presentedViewController == potentiallyPresentedViewController { return true } if let navigationController = potentiallyPresentedViewController.navigationController { if navigationController.presentingViewController?.presentedViewController == navigationController { return true } } return potentiallyPresentedViewController.tabBarController?.presentingViewController is UITabBarController }