2009-04-16 13 views
6

Tengo un UITabBarController, y cada pestaña maneja un UIViewController diferente que empuja a la pila a los nuevos controladores según sea necesario. En dos de estas pestañas necesito, cuando se alcanza un controlador específico, la capacidad de rotar el iPhone y visualizar una vista en modo horizontal. Después de luchar mucho, he encontrado que es obligatorio subclasificar UITabBarController para anular shouldAutorotateToInterfaceOrientation. Sin embargo, si simplemente devuelvo SÍ en la implementación, aparece el siguiente efecto secundario indeseable:tabBarController y navigationControllers en modo apaisado, episodio II

cada controlador en cada pestaña se pone automáticamente en modo horizontal cuando se gira el iPhone.

Incluso anulando shouldAutorotateToInterfaceOrientation en cada controlador para devolver NO no funciona: cuando se gira el iPhone, el controlador se pone en modo horizontal.

he implementado shouldAutorotateToInterfaceOrientation como sigue en el UITabBarController subclases:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    if([self selectedIndex] == 0 || [self selectedIndex] == 3) 
     return YES; 

    return NO; 
} 

de modo que sólo las dos lengüetas estoy realmente interesado en obtener apoyo para el modo horizontal. ¿Hay alguna manera de admitir el modo horizontal para un controlador específico en la pila de una pestaña determinada?

he intentado, sin éxito, algo así como

(BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation {

if([self selectedIndex] == 0 || [self selectedIndex] == 3) 
{ 
    if ([[self selectedViewController] isKindOfClass: [landscapeModeViewController class]]) 
      return YES; 
    } 

    return NO; 

}

Además, he intentado usar el método delegado didSelectViewController, sin éxito . Cualquier ayuda es muy apreciada. Gracias.

Respuesta

4

Esto funcionó para mí:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    if(self.selectedIndex == 0 && [[[self.viewControllers objectAtIndex:0] visibleViewController] isKindOfClass:[MyViewController class]]) 
     return YES; 
    else 
     return NO; 
} 
+0

Rich, muchas gracias. La solución propuesta funciona como un encanto ;-) ¡Este problema me estaba volviendo loco! No me di cuenta de que la forma correcta de hacerlo también requiere verificar simultáneamente el visibleViewController. ¡Gran respuesta! –

7

Aquí es una extensión para que los delegados UITabBarController llamadas a shouldAutorotateToInterfaceOrientation al controlador niño seleccionado en ese momento. Al usar esta extensión, ya no necesita subescribir UITabBarController y puede usar shouldAutorotateToInterfaceOrientation en sus controladores como uno esperaría.

UITabBarController + Autorotate.h:

#import <UIKit/UIKit.h> 

@interface UITabBarController (Autorotate) 
@end 

UITabBarController + Autorotate.m:

#import "UITabBarController+Autorotate.h" 

@implementation UITabBarController (Autorotate) 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    UIViewController *controller = self.selectedViewController; 
    if ([controller isKindOfClass:[UINavigationController class]]) 
     controller = [(UINavigationController *)controller visibleViewController]; 
    return [controller shouldAutorotateToInterfaceOrientation:interfaceOrientation]; 
} 

@end 
+1

En realidad esto ni siquiera es necesario. UITabBarController parece hacer algo similar, pero solo acepta orientaciones, todos los controladores de cada pestaña son compatibles. – Zargony

+0

Andreas, ¡eso sería una gran noticia! Pero no estoy viendo eso en mi aplicación. En mi caso, a menos que mueva la solicitud al controlador de vista, la solicitud de rotación nunca llega. Tan pronto como lo coloque, primero se le pedirá al controlador de la barra de pestañas, luego podré propagarlo al VC. Si hay algo que me falta, ¡por favor avise! De hecho, sigo teniendo problemas cuando el VC está dentro de la sección "Más" de la Barra de pestañas. En ese caso, el controlador de la barra de pestañas nunca se llama. :( –

+0

He publicado mi saga en un nuevo hilo. Http://is.gd/2emkj (redirige a stackoverflow.com) –

3

he sido capaz de utilizar este hace un tiempo (desde el controlador de la barra de pestañas de mi aplicación) sin problemas:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation]; 
} 

de esta manera, en el VC apropiada, tenemos que hacer la reales cheque, en este caso para una vista galería de fotos (¿qué otra cosa?):

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    // Return YES for supported orientations 
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 
} 

Mi opinión galería no es ni siquiera en la parte superior de la pila para un controlador de navegación determinada. Todavía se llama.

Ay, acabo de descubrir que este no funciona tan bien cuando la VC se esconde dentro de la MoreViewController (en contraposición a las cuatro pestañas principales). En ese caso, mi galería VC nunca se llama. Creo que es porque el VC al que he llamado desde el principio es realmente el controlador de navegación de la pestaña seleccionada, que luego propaga las cosas al VC apropiado, en este caso mi galería de fotos VC. Pero para el Más VC, las cosas no funcionan tan bien ... y las cosas van cuesta abajo rotativamente desde allí. : \

Traté de usar las modificaciones de Andreas (ver en otro lugar de este hilo), fue en vano. Pistas bienvenidas!

+0

¡Ah, ja! Cuando trato de rotar la interfaz, y SOLAMENTE cuando estoy usando un VC dentro del Controlador de Más Vista, veo esto en el registro de mi consola: "Usar la animación de rotación de dos etapas. Para usar la animación de etapa única más suave, esta aplicación debe eliminar las implementaciones de métodos de dos etapas." Umm ... news flash, NO estoy usando animación en dos etapas. Es decir, no estoy respondiendo a willAnimateSecondHalfOfRotationFromInterfaceOrientation: duration: en absoluto. Aparentemente, el controlador More view es, y por lo tanto, nunca recibo la llamada a willAnimateRotationToInterfaceOrientation: duration:. .. :( –

+0

De hecho, si trato de buscar la versión de SecondHalf ... tampoco recibo esa llamada. Hmm ... –

2

Me encontré con los mismos problemas que cuando trabajaba con el UITabBarController. Necesitaba controlar qué UIViewControllers podían rotar y cuáles no. Mi problema principal fue con la pestaña MÁS. No quería que gire ninguno de los UIViewControllers incluidos en la pestaña MÁS.

Mi solución fue crear mi propia UITabBarController que he llamado MyTabBarController:

@interface MyTabBarController : UITabBarController <UITabBarDelegate> { 

} 

Entonces implementado el método shouldAutorotateToInterfaceOrientation:

@implementation MyTabBarController 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
UIViewController *controller = [self selectedViewController]; 

if ((controller == [self moreNavigationController]) || ([self selectedIndex] == 4)) 
{ 
    return interfaceOrientation == UIInterfaceOrientationPortrait; 
} 

return [controller shouldAutorotateToInterfaceOrientation:interfaceOrientation]; 
} 

@end 

que necesitaba para descubrir si se ha seleccionado la pestaña MÁS. Este es un proceso de dos pasos; cuando se selecciona inicialmente la pestaña MORE, la API devuelve un selectedIndex superior a 4, así que necesitaba comparar el controlador seleccionado con el másNavigationController.

Si se selecciona un UIViewController dentro de la pestaña MÁS, el selectedIndex finalmente es 4, pero el Controlador seleccionado ya no es el Controlador de navegación más sino el UIViewController seleccionado.

if ((controller == [self moreNavigationController]) || ([self selectedIndex] == 4)) se encarga de este problema.

Ahora, cuando ejecuto mi aplicación, mis UIViewControllers en la pestaña MÁS no se rotan. Espero que esto ayude a otros desarrolladores que están teniendo los mismos problemas que yo.

Emilio

+0

Gracias. Tuve que implementar esto porque estaba creando mi tabbarcontrolador programáticamente y parece que no pudo t encuentre el método shouldAutorotateToInterfaceOrientation, incluso si está definido en el mismo viewcontroller o appdelegate. Tuve que hacer esto para apoyar el cambio de orientación en iOS5, no es necesario en iOS6 – estemendoza

0

Gracias, Gracias, Gracias. Han pasado 2 días para descubrir cómo hacer esto. Aquí está mi opinión sobre toda tu gran ayuda cuando tienes un tabBarController con navigationControllers.

- (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation {

UIViewController *controller = self.selectedViewController; 
if ([controller isKindOfClass:[UINavigationController class]]) 
    controller = [(UINavigationController *)controller visibleViewController]; 

if([controller isKindOfClass:[LOCviewcontroller class]]) 
    return YES; 
else 
    if([controller isKindOfClass:[personWebSiteView class]]) 
     return YES; 
else return NO; 

}

Cualquier crítica de código de un codificador neophite es siempre apreciada ... jack

0

¿Es realmente bien a subclase UITabBarController (como se sugiere en la respuesta aceptada arriba)?

He entendido que Apples dice algo así como "nunca deberías subclasificar UITabBarController o UINavigationController" - ¿o he entendido mal?

De todos modos; Encontré this tutorial donde subclasifican un UIViewController en el que ponen un UITabBarController.

1

Por lo que he visto aquí y en otras partes he cosido una solución que usa el método shouldAutorotate ya que la anterior shouldAutorotateToInterfaceOrientation ha quedado obsoleta.

Lo he colocado dentro de una categoría para UITabBarController. ¡Espero que esto sea admisible!

// call to method shouldAutorotate replaces call to method shouldAutorotateToInterfaceOrientation (deprecated) 
-(BOOL)shouldAutorotate 
{ // check whether selected view controller should autorotate  
    UIViewController *controller = self.selectedViewController; 
    if ([controller isKindOfClass:[UINavigationController class]]) 
    { // in case it is a navigation controller: get visible view of that 
     controller = [(UINavigationController *)controller visibleViewController]; 
    } 
    return [controller shouldAutorotate]; 
} 
Cuestiones relacionadas