Pregunta

ACTUALIZACIÓN: Véase mi respuesta a esta pregunta primero. Esto parece ser un error. Un caso de prueba mínimo ha sido creado y un informe se ha presentado con Apple. (Fijo como del iPhone OS 3.1.)

Esto es un puzzle de la "Estoy tan cerca!" departamento.

Tengo una aplicación para el iPhone basado en la barra de pestañas. Cada ficha cuenta con un UINavigationController con los sospechosos habituales (barra de navegación, la vista tabla ... que a su vez puede conducir a otra VC, etc.).

Ahora, uno de esos VC de nivel inferior es para ser utilizado en portait y los modos horizontal. Pero hay un problema. Nuestro paisaje ambiente de VC shouldAutorotateToInterfaceOrientation: no se llamará fuera de la caja! ¿Qué hacer?

Esto es lo que hacemos. En mi barra de control Tab, que he implementado en su propio archivo, tengo esto:

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

Esto termina la propagación de la solicitud a mi VC paisaje ambiente, que también responde a este mensaje. Todos mis otros VCs no implementan este método, por lo que sólo tiene que ir con la orientación vertical por defecto.

Problema resuelto !!! Yay!

Bueno, no del todo . (

Parece que las cosas no van tan bien cuando mi paisaje de usar VC se invoca dentro de las profundidades del controlador de la barra de pestañas MoreNavigationController .

decidí comparación / contraste entre un VC llamada desde dentro de uno de los primero Barra de cuatro pestaña UINavigationControllers ... y ese mismo VC llamada desde dentro de la MoreNavigationController . Esto va a ser un poco de ultra-detallada, así que tengan paciencia conmigo. Esperemos que el juego por el juego resulta útil para cosas de detective fuera.

Cuando las cargas de aplicaciones, hay varias llamadas iniciales a shouldAutorotate del controlador de la barra de pestañas ... método. En estos casos tempranos, selectedViewController es nula. Sin embargo, al final termina de cargar, se selecciona el elemento inicial pestaña, y todo está bien.

Derecho. En primer lugar, vamos a elegir uno de los cuatro primeros elementos de barra de pestaña y profundizar en nuestra CV.

Lo buscaremos tercer elemento de la barra de navegación, por lo que es el tercer controlador de navegación. Nos profundizar en nuestra CV que soporta rotación. Una rápida inspección confirma que el padre es de hecho el tercer controlador de navegación de la lista controlador de vista de nuestra barra de pestañas. Bueno!

Vamos a girar el dispositivo. Se le pide al controlador de barra de pestañas para autorotate (ver el código anterior). Observamos que selectedViewController es también que tercera controlador nav, además de los controladores de Vista superior y visible del controlador nav están establecidos en nuestro VC de confianza que soporta rotación.

Por lo tanto, el controlador de la barra de pestañas remitirá el shouldAutorotate mensaje hacia el tercer controlador de navegación ... pero nuestra rotación VC-amigable en última instancia reciba el mensaje. (No estoy haciendo nada especial aquí. Tal vez el VC deseada recibe el mensaje porque es la parte superior y / o VC visible?) En cualquier caso, hacemos girar con el paisaje, las cosas cambian de tamaño, y todo está bien. "Un gran éxito!"

Ahora vamos a golpear ese botón atrás y saca la pila de VC, dejando el modo horizontal en el proceso. El controlador de barra de pestañas se consulta de nuevo.

Es hora de un poco de lado aquí. La topViewController para nuestro controlador de navegación sigue siendo que la rotación VC-amigable, pero visibleViewController se establece ahora en UISnapshotModalViewController ! Je. Nunca vi esto antes ... pero Erica Sadun ha . Parece que es para "desaparecer los controladores de vista". (Que en este caso es cierto - está desapareciendo bien)

Como sigo paso a paso a través, lo visible VC queda como instantánea, pero la parte superior VC con el tiempo cambia a la siguiente VC en la pila, ya que mi VC especial finalmente se ha ido. Justo lo suficiente.

Entonces es los escenarios WHantes de que todo funciona bien.

Ahora vamos a tratar de la misma prueba, sólo que esta vez vamos a ir a la MoreNavigationController (el elemento de la barra Más pestaña) y profundizar en la misma clase VC como antes. En mi caso pasa a ser el séptimo en una lista de VC del controlador de la barra de pestañas.

Entramos en la rotación VC-conscientes y ... esta vez se le preguntó a girar directamente ! El controlador de barra de pestañas es no pidió permiso para girar en absoluto. Hmm.

Una revisión rápida de la matriz VC muestra que es un MoreNavigationController . OK, eso tiene sentido.

Ahora vamos a tratar de hacer girar el dispositivo. NADA es llamada . Ninguno de nuestros puntos de interrupción recibe un golpe. No en nuestro VC. No en nuestro controlador de la barra de pestañas. (¿Qué?!?!)

O-kaaaay. Vamos a sacar la pila, volver a entrar en el mismo VC y tratar de girar de nuevo. Extraño. Ahora tenemos una llamada en la barra de control Tab pidiendo permiso auto rotación. A continuación, el controlador seleccionado es nuestro controlador de navegación de confianza (# 7), pero esta vez su visibleViewController y topViewController son asigna nil

Una vez que continuamos desde aquí, aparece un misterioso mensaje en la consola de depuración:

  

Uso de animación rotación de dos etapas. A   utilizar la sola etapa más suave   animación, esta solicitud debe   eliminar método de dos etapas   implementaciones.

Misteriosa porque No estoy usando la rotación de la animación de dos etapas ! No segundosemestre variantes del método están en juego en cualquier parte de mi código fuente.

Por desgracia, mi VC-rotación en cuenta que nunca se le dice que se está produciendo la rotación (a pesar de que la rotación se produce en la pantalla), así que por supuesto mi punto de vista es todo lo elevado de foul como resultado. Caos y tristeza sobrevienen. : (

No vamos a siquiera se molestan hacer estallar la pila en este punto.

Creo que los consejos doc Ver Controller en el posible problema:

  

Si desea realizar personalizada   animaciones durante una orientación   cambio, puede hacerlo en uno de los dos   formas. cambios de orientación utilizados para   ocurrir en dos etapas, con notificaciones   se produce en el comienzo, medio,   y puntos finales de la rotación.   Sin embargo, en el iPhone OS 3.0, el apoyo fue   añadido para realizar la orientación   cambios en un paso. El uso de un solo paso   cambio de orientación tiende a ser más rápido   que el antiguo proceso de dos pasos y es   generalmente se recomienda para cualquier nuevo   código.

Me pregunto si MoreNavigationController continuará respondiendo al proceso de dos pasos, y por lo tanto se tropezar cualquier intento de utilizar el proceso de un solo paso? Tenga en cuenta que, si responde a los mensajes de dos pasos, la variante de un solo paso no funcionará (de nuevo, por los documentos). No estoy respondiendo a ellas, pero tengo la sospecha de algo detrás de las escenas de ES.

De hecho, si comento a cabo el método de un solo paso, y tratar de responder a willAnimateSecondHalfOfRotationFromInterfaceOrientation: duración: , I no consiguieron la nota! Pero aún así no sobresalen de la pila de forma muy limpia (en términos de efectos visuales). Aún más extraño: willAnimateFirstHalfOfRotationFromInterfaceOrientation: duración: no se llama, incluso cuando trataba de colarse una llamada a la libre (utilizando el mensaje FirstHalf) en shouldAutorotateToInterfaceOrientation: . Se vuelve inmediatamente durante un recorrido, como si ni siquiera definido. Suspiro.

Así que por el play-by-play.

En resumen, ha cualquiera manejado con éxito la rotación dispositivo de un solo paso para un VC invoca dentro de una MoreNavigationController de barra de control Tab? La gente informada quieren saber!

¿Fue útil?

Solución

Apple desaconseja UITabBarController subclases, así que encontró una manera fácil de manejar autorrotación utilizando categorías lugar. No se soluciona el error con los Más ... controladores de vista, pero creo que es una forma más de Apple de usar de conseguir el trabajo hecho (y significa menos de subclases para usted).

Para hacer que cada pestaña en mi autorotate aplicación correctamente, he definido -shouldAutorotateToInterfaceOrientation: en mis controladores de vista personalizada, pero son todos UINavigationControllers interior dentro de un UITabBarController, por lo que el mensaje no son enviadas de abajo de la cadena a mi VC hasta que los dos también responder. Por lo que añade las siguientes líneas a mis archivos delegado de la aplicación:

  

Añadido a la parte inferior de MyAppDelegate.h

@interface UITabBarController (MyApp)
@end

@interface UINavigationController (MyApp)
@end
  

Añadido a la parte inferior de MyAppDelegate.m

@implementation UITabBarController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return YES;
}
@end

@implementation UINavigationController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return YES;
}
@end

Otros consejos

Parece ser que tenemos un error. He creado un caso de prueba reproducible, mínimo, e informó que a través de Apple Informar de fallos ( RADAR Problema 7139857 ) .

Actualización:. Esto se ha corregido a partir del iPhone OS 3.1

El problema esencial es:

  

Vista controladores que ya están en una   Controlador de pila de navegación no hacer   recibir    willAnimateRotationToInterfaceOrientation: duración:   mensajes cuando una barra de pestañas de Controlador   'Controlador Más de Navegación' en   utilizar.

Este problema se hace no ocurrir cuando los controladores de vista pestaña elemento de la barra son los controladores de vista básicos. Sólo cuando son controladores de navegación y solamente cuando la jerarquía de navegación "Más" está en uso.

El mensaje de la consola (en relación con la animación de rotación de dos etapas) sugiere que algo dentro del marco (el más Controlador de Navegación?) Sigue utilizando una animación de dos etapas, a pesar de una sola etapa se recomienda ahora a partir del iPhone OS 3.0.

Esto podría explicar por qué willAnimateRotationToInterfaceOrientation: no se llama en ese caso particular. Por visión documentación controladora de Apple, este mensaje no será invocado cuando en dos etapas, primeros mensajes en la segunda mitad de orientación / están siendo respondió a su lugar.

A ligeramente modificada versión de respuesta de victorb que permite a cada controlador de vista única para decidir si se permite la rotación.

Aquí, como una esencia para facilitar la copia y se bifurcan

AppDelegate.h

@interface UITabBarController (MyApp)
@end

@interface UINavigationController (MyApp)
@end

AppDelegate.m

@implementation UITabBarController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    UIViewController *selectedVC = [self selectedViewController];
    if ([selectedVC respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
        return [selectedVC shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
    }

    //optimistic return - if you want no rotation, you have to specifically tell me!
    return YES;
}
@end

@implementation UINavigationController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    UIViewController *visibleVC = [self visibleViewController];
    if ([visibleVC respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
        return [visibleVC shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
    }

    //optimistic return - if you want no rotation, you have to specifically tell me!
    return YES;
}
@end
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top