En iOS6, problemas para forzar ViewController a cierta interfaceOrientation cuando se empuja en la stack

Tengo la siguiente configuración de controlador de vista:

viewController1 puede rotar libremente a cualquier orientación, excepto el retrato al revés.

viewController2 se coloca encima de viewController1, y me gustaría que fuera la misma orientación que viewController1 y me gustaría que no pueda rotar.

viewController3 se coloca encima de viewController2. Me gustaría que viewController3 esté en modo vertical.

Tengo muchos problemas para lograr esto en iOS6 (aún no lo intenté en iOS5). Primero, ya creé mi propio Controlador de navegación y puse lo siguiente en él:

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return [self.topViewController preferredInterfaceOrientationForPresentation]; } - (NSUInteger)supportedInterfaceOrientations { return [self.topViewController supportedInterfaceOrientations]; } - (BOOL) shouldAutorotate { return [self.topViewController shouldAutorotate]; } 

He intentado muchas combinaciones diferentes de estas cosas para saber aprovechar. Principalmente donde estoy luchando es forzar vc3 para presentarse como retrato si vc2 está en el paisaje. Cualquier ayuda sería apreciada.

Lo que estás tratando de hacer aquí es luchar contra el marco. Lo que está describiendo simplemente no es cómo funciona una architecture de controlador de navegación en iOS 6. Si desea mostrar la vista de un controlador de vista y la rotación forzada, use un controlador de vista presentado. Esa es la única vez que preferredInterfaceOrientationForPresentation tiene sentido, y las directuresInterfaceOrientations de su controlador de vista serán realmente consultadas porque, al presentarse, estarán en la raíz de la interfaz.

He explicado en una respuesta diferente que no es compatible, en iOS 6, para forzar la rotación cuando se empuja un nuevo controlador de vista a un controlador de navegación. Puede estructurar reglas sobre la rotación compensatoria (es decir, qué debería suceder si el usuario gira el dispositivo ), pero no puede forzar la rotación de la interfaz. La única situación en la que iOS 6 está feliz de permitirle forzar la rotación es cuando presenta o descarta un controlador de vista ( presentViewController:animated: y dismissViewControllerAnimated: .

Sin embargo, es posible usar un controlador de vista presentado de tal manera que parece que está presionando el controlador de navegación. Hice una película que muestra lo que quiero decir:

http://youtu.be/O76d6FhPXlE

Ahora, eso no es totalmente perfecto de ninguna manera. No hay animación de rotación de la barra de estado, y hay una especie de “parpadeo” negro entre las dos vistas, que es intencional, porque está ahí para ocultar lo que realmente está sucediendo. Lo que realmente está sucediendo es que realmente hay dos controladores de navegación diferentes y tres controladores de vista, como se muestra en esta captura de pantalla del guión gráfico.

enter image description here

Lo que tenemos es:

  • una subclase de controlador de navegación establecida en orientación vertical y su controlador de vista raíz

  • una segunda subclase de controlador de navegación establecida en orientación horizontal, y su controlador de vista raíz, que es negro y funciona como un intermediario

  • un tercer controlador de vista para ser empujado a la stack del segundo controlador de navegación

Cuando el usuario pide “avanzar” desde el primer controlador de vista, presentamos el segundo controlador de navegación, viendo el controlador de vista negro momentáneamente, pero luego inmediatamente presionamos el tercer controlador de vista. Entonces tenemos rotación forzada, junto con una especie de flash negro y una animación push. Cuando el usuario toca el botón Atrás en el tercer controlador de vista, invertimos el proceso.

Todo el código de transición está en el controlador de vista en negro (ViewControllerIntermediary). Intenté ajustarlo para dar la animación más satisfactoria posible:

 @implementation ViewControllerIntermediary { BOOL _comingBack; } - (void) viewDidLoad { [super viewDidLoad]; self.navigationController.delegate = self; } -(void)navigationController:(UINavigationController *)nc willShowViewController:(UIViewController *)vc animated:(BOOL)anim { if (self == vc) [nc setNavigationBarHidden:YES animated:_comingBack]; else [nc setNavigationBarHidden:NO animated:YES]; } -(void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if (!_comingBack) { [self performSegueWithIdentifier:@"pushme" sender:self]; _comingBack = YES; } else [self.navigationController dismissViewControllerAnimated:YES completion:nil]; } 
 - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { if ([self.window.rootViewController.presentedViewController isKindOfClass: [SecondViewController class]]) { SecondViewController *secondController = (SecondViewController *) self.window.rootViewController.presentedViewController; if (secondController.isPresented) return UIInterfaceOrientationMaskAll; else return UIInterfaceOrientationMaskPortrait; } else return UIInterfaceOrientationMaskPortrait; } 

Y para Swift

 func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow) -> Int { if self.window?.rootViewController?.presentedViewController? is SecondViewController { let secondController = self.window!.rootViewController.presentedViewController as SecondViewController if secondController.isPresented { return Int(UIInterfaceOrientationMask.All.toRaw()); } else { return Int(UIInterfaceOrientationMask.Portrait.toRaw()); } } else { return Int(UIInterfaceOrientationMask.Portrait.toRaw()); } } 

Para más detalles, consulte este enlace