tab que bar objective-c cocoa-touch uiviewcontroller uinavigationcontroller device-orientation
Descarga la aplicación (proyecto XCode)

objective c - bar - ¿Cómo restringir la autorrotación a una única orientación para algunas vistas, mientras que permite todas las orientaciones en otras?



uiviewcontroller lifecycle (5)

Cree un bolean en el delegado de la aplicación para controlar qué orientación desea, por ejemplo, haga un bool para habilitar Portrait y en su controlador de vista desea permitir que Portrait lo habilite mediante una aplicación compartida

en su controlador de vista, donde desea habilitar o deshabilitar cualquier orientación que desee.

((APPNAMEAppDelegate *)[[UIApplication sharedApplication] delegate]).enablePortrait= NO;

en la aplicación de delegado.

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { NSLog(@"Interface orientations"); if(!enablePortrait) return UIInterfaceOrientationMaskLandscape; return UIInterfaceOrientationMaskLandscape|UIInterfaceOrientationMaskPortrait; }

Este método se activará cada vez que gire el dispositivo. Según estos BOOL, habilite la orientación que desee.

Esta pregunta es sobre la rotación de dispositivos iOS y múltiples vistas controladas en un UINavigationController. Algunas vistas deben limitarse a la orientación vertical , y otras deben autorotearse libremente . Si intentas crear la configuración más simple con tres vistas, notarás que el comportamiento de autorrotación tiene algunos caprichos muy desagradables. El escenario es, sin embargo, muy simple, así que creo que o no estoy haciendo la implementación de autorrotación correctamente, o me estoy olvidando de algo.

Tengo una aplicación de demostración muy básica que muestra la rareza, e hice un video que lo muestra en acción.

La configuración es muy básica: tres controladores de vista denominados FirstViewController , SecondViewController y ThirdViewController extienden un AbstractViewController que muestra una etiqueta con el nombre de la clase y que devuelve SÍ para shouldAutorotateToInterfaceOrientation: cuando el dispositivo está en orientación vertical. El SecondViewController anula este método para permitir todas las rotaciones. Las tres clases concretas agregan algunos cuadrados de colores para poder navegar entre las vistas presionando y colocando los controladores en / fuera del UINavigationController . Hasta aquí un escenario muy simple, diría yo.

Si sostienes el dispositivo en orientación vertical u horizontal, este es el resultado que no solo me gustaría lograr, sino que también esperaría. En la primera imagen, verá que todas las vistas están "en posición vertical", y en la segunda, verá que solo el segundo controlador de vista rota la orientación del dispositivo. Para ser claros, debería ser posible navegar desde la segunda vista en modo horizontal a la tercera, pero como esa tercera solo admite la orientación vertical, solo debe mostrarse en orientación vertical. La forma más fácil de ver si los resultados son correctos, es observando la posición de la barra portadora.

Pero esta pregunta está aquí porque el resultado real es completamente diferente. Dependiendo de la vista en la que se encuentre cuando gira el dispositivo, y dependiendo de la vista a la que vaya a continuación, las vistas no girarán (para ser específico, el método didOrientFromInterfaceOrientation: nunca se llama). Si estás en el paisaje en el segundo y navegas hasta el tercero, tendrá la misma orientación que el segundo (= malo). Sin embargo, si navega desde el segundo hasta el primero, la pantalla cambiará a un modo de retrato "forzado" y la barra del operador estará en la parte superior física del dispositivo, independientemente de cómo lo sostenga. El video muestra esto con más detalle.

Mi pregunta es doble:

  1. ¿Por qué el primer controlador de vista rota hacia atrás, pero no el tercero?
  2. ¿Qué debe hacerse para obtener el comportamiento correcto de sus vistas cuando solo quiere que algunas vistas se autorroteen, pero no otras?

Saludos, EP.

EDITAR: Como último recurso antes de darle una recompensa, reescribí completamente esta pregunta para que sea más breve, más clara y, con suerte, más invitadora a dar una respuesta.


En iOS 6, esto se ha convertido en un problema muy simple. Simplemente crea una clase especial para las vistas que deseas autorotizar. Luego, en su rootVC, agregue esto.

-(BOOL)shouldAutorotate{ BOOL should = NO; NSLog(@"%@", [self.viewControllers[self.viewControllers.count-1] class]); if ([self.viewControllers[self.viewControllers.count-1] isKindOfClass:[YourAutorotatingClass class]]) { should = YES; } return should; }

Sé que esta es una vieja pregunta, pero pensé que valía la pena mencionarla.


Hace unos años hubo una pregunta similar con varias respuestas. Aquí hay una respuesta reciente de alguien a esa pregunta:
¿Hay alguna forma documentada de configurar la orientación del iPhone?

Por lo que entiendo, este es un problema que mucha gente tiene y la mayoría de los piratas informáticos son la única forma de solucionarlo. Mire a través de ese hilo si no lo ha visto antes y vea si algo funciona para usted.

En una nota al margen, tuve un problema similar hace un tiempo cuando estaba llamando a algo que debía ser Autoregado y agregué algo de código a viewWillAppear para intentar solucionarlo. Honestamente no recuerdo si funcionó y ya no tengo una Mac para probarlo, pero encontré el código y lo pegué aquí en caso de que me sirva de inspiración.

- (void)viewWillAppear:(BOOL)animated{ UIInterfaceOrientation o; switch ([UIDevice currentDevice].orientation) { case UIDeviceOrientationPortrait: o = UIInterfaceOrientationPortrait; break; case UIDeviceOrientationLandscapeLeft: o = UIInterfaceOrientationLandscapeLeft; break; case UIDeviceOrientationLandscapeRight: o = UIInterfaceOrientationLandscapeRight; break; default: break; } [self shouldAutorotateToInterfaceOrientation:o]; }


La respuesta corta es que está utilizando UINavigationController, y eso no funcionará como usted quiere. De los documentos de Apple:

¿Por qué mi UIViewController no gira con el dispositivo?

Todos los controladores de vista secundarios en su UITabBarController o UINavigationController no están de acuerdo con un conjunto de orientación común.

Para asegurarse de que todos los controladores de vista secundarios giren correctamente, debe implementar shouldAutorotateToInterfaceOrientation para cada controlador de vista que represente cada pestaña o nivel de navegación. Cada uno debe estar de acuerdo con la misma orientación para que ocurra esa rotación. Es decir, todos deberían devolver SÍ para las mismas posiciones de orientación.

Puede leer más sobre los problemas de rotación de la vista aquí .

Tendrá que rodar su propia gestión de pila de vista / controlador para lo que quiere hacer.


NO UTILICE ESTE HACK, APPLE RECHAZARÁ LA APLICACIÓN EN BASE AL USO DE ''API PRIVADA''

En aras de la referencia, dejaré mi respuesta aquí, pero el uso de la API privada no pasará del panel de revisión. Aprendí algo hoy: D Como @younce citó los documentos de Apple correctamente, lo que quiero no se puede lograr con UINavigationController.

Tuve dos opciones. Primero, podría haber escrito mi propio sustituto de controlador de navegación, con todos los horrores que uno podría haber encontrado mientras lo hacía. En segundo lugar, podría haber pirateado la rotación en los controladores de vista, utilizando una función no documentada de UIDevice llamada setOrientation:animated:

Porque el segundo fue tentadoramente fácil, fui por eso. Esto es lo que hice. Necesitarás una categoría para suprimir las advertencias del compilador sobre el setter que no existe:

@interface UIDevice (UndocumentedFeatures) -(void)setOrientation:(UIInterfaceOrientation)orientation animated:(BOOL)animated; -(void)setOrientation:(UIInterfaceOrientation)orientation; @end

Luego debe verificar las orientaciones admitidas en viewWillAppear: Junto a los métodos de UIDevice utilizados aquí, también podría forzar la orientación de retrato al presentar un controlador de vista modal, pero eso sucederá instantáneamente y no se animará, por lo que esta es mi forma preferida:

-(void)viewWillAppear:(BOOL)animated { UIDevice *device = [UIDevice currentDevice]; UIDeviceOrientation realOrientation = device.orientation; if ([self shouldAutorotateToInterfaceOrientation:realOrientation]) { if (realOrientation != [UIApplication sharedApplication].statusBarOrientation) { // Resetting the orientation will trigger the application to rotate if ([device respondsToSelector:@selector(setOrientation:animated:)]) { [device setOrientation:realOrientation animated:animated]; } else { // Yes if Apple changes the implementation of this undocumented setter, // we''re back to square one. } } } else if ([self shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationPortrait]) { if ([device respondsToSelector:@selector(setOrientation:animated:)]) { // Then set the desired orientation [device setOrientation:UIDeviceOrientationPortrait animated:animated]; // And set the real orientation back, we don''t want to truly mess with the iPhone''s balance system. // Because the view does not rotate on this orientation, it won''t influence the app visually. [device setOrientation:realOrientation animated:animated]; } } }

El truco es mantener siempre la orientación interna del dispositivo a la orientación "real" del dispositivo. Si comienzas a cambiar eso, la rotación de tu aplicación estará fuera de balance.

Pero como sé ahora, esta es solo una forma segura de que su aplicación sea rechazada. Así que la opción número dos es simplemente una mala opción. Reescribe ese NavigationController, o simplemente haz que todas tus vistas sean compatibles con el mismo conjunto de orientación.

Saludos, EP.