Cómo manejar diferentes orientaciones en iOS

AGREGADO: puede acceder a este proyecto en github ios6rotations


Lo siento chicos por hacer la pregunta sobre la rotation de pantalla en iOS 6, pero esto es realmente un dolor en el culo … 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 de vistas simple en mi aplicación de testing:

Lo que bash lograr es mantener el controller azul solo en el paisaje y el rojo solo está en retrato .

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

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

En mi controller azul implementé esto:

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

Y en el controller rojo esto:

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

Ahora tengo el siguiente comportamiento:

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

PD Todos mis methods de rotation (publicados anteriormente) reciben llamadas normalmente. (Por cierto, ¿por qué estos methods se llaman tantas veces por transición de pantalla? 5-6 veces)

- (UIInterfaceOrientation)prefernetworkingInterfaceOrientationForPresentation no - (UIInterfaceOrientation)prefernetworkingInterfaceOrientationForPresentation llamadas con empuje

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

La pregunta es: ¿cómo forzar la rotation a la orientación admitida en cada controller?

Te sugiero que publiques aquí (como respuestas) cualquier código de trabajo al 100% para manejar rotaciones en ios6 (por ejemplo, si tienes algo para iPad con SplitController), mantendré esta pregunta en favoritos para tener todo en un solo lugar cuando 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 rechazará su aplicación. Mira esta pregunta

Lo que pide no es posible utilizando API pública y tampoco se recomienda desde el punto de vista de HIG. Lo que se admite y se debe implementar, es la presentación modal de los diferentes controlleres de vista con una orientación de interfaz compatible diferente. Esta es la razón por la cual la implementación pnetworkingeterminada de UINavigationController es rotar siempre; Asume que todos los controlleres de vista tienen las mismas orientaciones de interfaz compatibles.

Tomemos por ejemplo la reproducción de video en iPhone. Abre las aplicaciones de video (que viene con iOS). El controller de la vista raíz solo admite la orientación vertical. Sin embargo, inicie un video y aparecerá un controller de vista modal que solo admite orientaciones de interfaz de paisaje. Esto parece exactamente el comportamiento que deseas lograr.

Esta es la razón por la que no se llama a PrefernetworkingFunctionOrientationForPresentation. prefernetworkingInterfaceOrientationForPresentation solo se presentViewController:animated: al usar presentViewController:animated:

Una pequeña gotcha, si necesita una barra de navigation en cada etapa de su escena, necesitará adjuntar cada controller de vista modal con un controller de navigation. A continuación, puede pasar los datos necesarios en prepareForSegue: accediendo a topViewController del object del controller de navigation en el segue.


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

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

Mis dos centavos vale la pena.

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

Además, en el guión gráfico, puede establecer visualmente la orientación de la class ViewController en el paisaje .

use esta línea para cambiar la orientación mediante progtwigción … trabaje 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 código siguiente en su file de implementación .. en la parte superior.

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

y después de eso en el método siguiente simplemente escriba 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 count que no estoy usando UINavigationController).

Cambie los methods shouldAutorotate en ambos viewControllers:

 //in blue (landscape only) -(BOOL)shouldAutorotate{ if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { return YES; } else { return NO; } } //in networking (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 methods supportInterfaceOrientations del mismo modo.

 #pragma mark- Orientation Delegate Method: - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { Orientation = [UIApplication shanetworkingApplication].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 usar juntos la navigation con orientación, debe tomar un montón de control de vista como una matriz.

Después de ese pago siguiendo los methods,

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

Estos cambios en sus methods lo ayudarán mucho.

¡Disfruta de la progtwigción!