Cómo manejar diferentes orientaciones en iOS

AGREGADO: Puede acceder a este proyecto en github ios6rotaciones


Lo siento chicos por hacer la pregunta sobre la rotación de pantalla en iOS 6, pero esto es realmente un dolor de cabeza … y todavía no puedo entenderlo por completo, por alguna razón se comporta de manera diferente bajo ciertas circunstancias.

Tengo la siguiente jerarquía simple de vistas en mi aplicación de prueba:

Lo que bash lograr es mantener el controlador azul solo en el paisaje y el rojo solo en el retrato .

Tengo una subclase de UINavigationController con dicho código dentro:

@implementation CustomNavController - (BOOL)shouldAutorotate { return [[self.viewControllers lastObject] shouldAutorotate]; } - (NSUInteger)supportedInterfaceOrientations { return [[self.viewControllers lastObject] supportedInterfaceOrientations]; } - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation { return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation]; } @end 

En mi controlador azul implementé esto:

 - (BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscape; } 

Y en el controlador rojo esto:

 - (BOOL)shouldAutorotate { return YES; } - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } 

Ahora tengo el siguiente comportamiento:

  1. La aplicación comenzó en el paisaje (OK)
  2. Cuando presiono el botón, mi controlador rojo también se desplazó horizontalmente (esto no está bien porque debe mostrarse en Vertical)
  3. Gira con éxito hacia el retrato pero no hacia atrás al paisaje
  4. Si dejo el controlador rojo en modo vertical, mi controlador azul (que está restringido al paisaje) se muestra en modo vertical.

PD: todos mis métodos de rotación (publicados anteriormente) se están llamando normalmente. (Por cierto, ¿por qué estos métodos se llaman tantas veces por transición de pantalla? 5-6 veces)

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation no se llama al presionar

Todas las orientaciones (excepto las de portraitUpsideDown) están incluidas en plist.

La pregunta es: ¿cómo forzar la rotación a la orientación compatible en cada controlador?

Te sugiero que publiques aquí (como respuestas) cualquier código que funcione al 100% para manejar rotaciones en ios6 (por ejemplo, si tienes algunas para iPad con SplitController) – Guardaré esta pregunta en favoritos para tener todo en un solo lugar cuando lo necesite para manejar algunas situaciones específicas. ¡Aclamaciones!

AGREGADO: No publique esto como respuesta de paisaje a retrato . Espero que haya una forma más elegante de hacerlo.

Usando -[UIDevice setOrientation:] es una API privada, y obtendrá su aplicación rechazada. Ver esta pregunta

Lo que usted pregunta no es posible usando la API pública y tampoco se recomienda desde el punto de vista HIG. Lo que sí se admite y lo que debe implementar es la presentación modal de los diferentes controladores de vista con una orientación de interfaz compatible diferente. Esta es la razón por la cual la implementación predeterminada de UINavigationController es rotar siempre; se supone que todos los controladores de vista tienen las mismas orientaciones de interfaz admitidas.

Tomemos como ejemplo la reproducción de video en iPhone. Abra las aplicaciones de video (que vienen con iOS). El controlador de vista raíz solo admite orientación vertical. Sin embargo, inicie un video y aparece un controlador de vista modal que solo admite orientaciones de interfaz de paisaje. Este parece ser exactamente el comportamiento que desea lograr.

Esta es la razón por la cual no se llama a preferredInterfaceOrientationForPresentation . preferredInterfaceOrientationForPresentation solo se presentViewController:animated: cuando se usa presentViewController:animated:

Una pequeña sorpresa, si necesita una barra de navegación en cada etapa de su escena, deberá encerrar cada controlador de vista modal con un controlador de navegación. A continuación, puede pasar los datos requeridos en prepareForSegue: accediendo a topViewController del objeto del controlador de navegación en la transición.


Aquí hay un proyecto de ejemplo que se comporta correctamente de acuerdo con sus requisitos (o al menos le dará ideas sobre cómo implementarlo):

http://www.mediafire.com/?zw3qesn8w4v66hy

Mis dos centavos valen la pena.

Puede presentar una vista modal transparente vacía rápidamente y luego descartarla , tal vez en ViewDidLoad: o viewWillAppear: en su clase ViewController y ViewController Second como una solución rápida.

Además, en el guión gráfico, puede establecer la orientación de la clase ViewController para ajardinar visualmente.

usa esta línea para cambiar la orientación programáticamente … trabaja al 100%

 [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight]; 

y también cuando agrega esta línea en ese momento, aparece una advertencia y para eliminar esta advertencia simplemente agregue el siguiente código en su archivo de implementación: en la parte superior.

 @interface UIDevice (MyPrivateNameThatAppleWouldNeverUseGoesHere) - (void) setOrientation:(UIInterfaceOrientation)orientation; @end 

y después de eso en el método de debajo solo escribe este código si es necesario ..

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return your supported orientations if (currentMainView==blueOne) { return toInterfaceOrientation== UIInterfaceOrientationPortrait; } } 

Tengo una situación similar en una de mis aplicaciones (aunque tenga en cuenta que no estoy usando UINavigationController).

Cambia los métodos de shouldAutorotate en tus viewControllers:

 //in blue (landscape only) -(BOOL)shouldAutorotate{ if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { return YES; } else { return NO; } } //in red (portrait only) -(BOOL)shouldAutorotate{ if (self.interfaceOrientation == UIInterfaceOrientationPortrait) { //note that UIInterfaceOrientationIsPortrait(self.interfaceOrientation) will return yes for UIInterfaceOrientationPortraitUpsideDown return YES; } else { return NO; } } 

Mantenga los métodos supportedInterfaceOrientations InterfaseOrientaciones iguales.

 #pragma mark- Orientation Delegate Method: - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { Orientation = [UIApplication sharedApplication].statusBarOrientation; if (Orientation == UIInterfaceOrientationLandscapeLeft || Orientation == UIInterfaceOrientationLandscapeRight) { // self.scrollView.contentOffset = CGPointMake(self.view.bounds.size.width,1200); [scrollView setScrollEnabled:YES]; [scrollView setContentSize:CGSizeMake(768, 2150)]; }else if (Orientation == UIInterfaceOrientationPortrait || Orientation == UIInterfaceOrientationPortraitUpsideDown) { [scrollView setScrollEnabled:YES]; [scrollView setContentSize:CGSizeMake(768, 1750)]; } } 

Para utilizar la navegación con orientación juntos, debe tomar un montón de controladores de vista como una matriz.

Después de esa comprobación, siguiendo los métodos,

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

estos cambios en tus métodos te ayudarán mucho.

¡Disfruta la progtwigción!