UITabBarController, MoreNavigationController y el Santo Grial de la rotación de dispositivos

ACTUALIZACIÓN: Ver mi respuesta a esta pregunta primero. Esto parece ser un error. Se ha creado un caso de prueba mínimo y se ha archivado un informe con Apple. (Corregido a partir de iPhone OS 3.1.)

Aquí hay un rompecabezas del "¡Estoy tan cerca!" Departamento.

Tengo una aplicación para iPhone basada en la barra de pestañas. Cada pestaña presenta unaUINavigationController con los sospechosos habituales (barra de navegación, vista de tabla ... que a su vez puede conducir a otra VC, etc.).

Ahora, uno de esos VC de nivel inferior se utilizará en el portaity modos de paisaje. Pero hay un problema. Nuestros VC's amigables con el paisajeshouldAutorotateToInterfaceOrientation: ¡No serás llamado fuera de la caja! ¿Qué hacer?

Esto es lo que hacemos. En mi Tab Bar Controller, que he implementado en su propio archivo, tengo esto:

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

Esto termina propagando la solicitud a mi VC amigable con el paisaje, que también responde a este mensaje. Todos mis otros VC no implementan este método, así que simplemente van con la orientación vertical predeterminada.

¡¡¡Problema resuelto!!! ¡Hurra!

Bien,no exactamente. :(

Parece que las cosas no van tan bien cuando se invoca mi VC amigable con el paisaje desde las profundidades del controlador de la barra de pestañasMoreNavigationController.

Decidí comparar / contrastar entre un VC llamado desde uno de losprimeros cuatro barra de pestañasControladores UINavigacion ... y ese mismo CV llamado desde dentro delMoreNavigationController. Esto va a ser un poco ultra detallado, así que tengan paciencia. Esperemos que el juego por el juego sea útil para analizar las cosas.

Cuando se carga la aplicación, hay varias llamadas iniciales al método shouldAutorotate ... del controlador de la barra de pestañas. En estos primeros casos,selectViewController es nulo Sin embargo, al final terminamos de cargar, se selecciona el elemento de la pestaña inicial y todo está bien.

Derecha. Primero, escojamos uno de los primeros cuatro elementos de la barra de pestañas y profundicemos en nuestro VC.

Elegiremos el tercer elemento de la barra de navegación, así que ese es el tercer controlador de navegación. Profundizamos en nuestro VC que soporta rotación. Una inspección rápida confirma que el principal es de hecho el tercer controlador de navegación de la lista de controladores de vista de la barra de pestañas. ¡Bueno!

Vamos a rotar el dispositivo. Se le pide al controlador de la barra de pestañas que gire automáticamente (consulte el código anterior). Observamos queselectViewController es también que el tercer controlador de navegación, más los controladores de vista superior y visible del controlador de navegación están configurados en nuestro VC de confianza que admite rotación.

Por lo tanto, el controlador de la barra de pestañas reenviará elDebería Autorizar mensaje al tercer controlador de navegación ... pero nuestro VC amigable con la rotación finalmente recibe el mensaje. (No estoy haciendo nada especial aquí. ¿Tal vez el VC deseado recibe el mensaje porque es el VC superior y / o visible?) En cualquier caso, rotamos al paisaje, las cosas cambian de tamaño y todo está bien. "¡Gran éxito!"

Ahora presionemos el botón Atrás y abramos la pila de VC, dejando el modo paisaje en el proceso. Se vuelve a consultar el controlador de la barra de pestañas.

Tiempo para un poco aparte aquí. lostopViewController para nuestro controlador de navegación sigue siendo ese VC amigable con la rotación, perovisibleViewController ahora está configurado paraUISnapshotModalViewController! Heh Nunca vi esto antes ... peroErica Sadun tiene. Parece que es para "controladores de vista que desaparecen" (lo que en este caso es cierto, está desapareciendo).

Mientras sigo avanzando, el VC visible permanece como Instantánea, pero el VC superior eventualmente cambia al siguiente VC en la pila, ya que mi VC especial eventualmente desaparece. Lo suficientemente justo.

Asi queeso es El escenario donde todo funciona bien.

Ahora intentemos la misma prueba, solo que esta vez vamos a ir a laMoreNavigationController (el elemento de la barra de pestañas Más) y profundice en la misma clase de VC que antes. En mi caso, es el séptimo en la lista de VC del controlador de la barra de pestañas.

Entramos en el VC consciente de la rotación y ... esta vez se le pide que giredirectamente! El controlador de la barra de pestañas esno Pidió permiso para rotar en absoluto. Hmm

Una comprobación rápida del VC principal muestra que es unMoreNavigationController. OK, eso tiene sentido.

Ahora vamos a tratar de girar el dispositivo.NADA SE LLAMA. Ninguno de nuestros puntos de ruptura se ve afectado. No en nuestro CV. No en nuestro controlador de barra de pestañas. (Huh?!?!)

O-kaaaay. Hagamos estallar la pila, regresemos al mismo VC e intentemos rotar nuevamente. Extraño. AHORA recibimos una llamada en el controlador de la barra de pestañas que solicita el permiso de autorotación. Aquí, el Controlador seleccionado es nuestro confiable controlador Nav (# 7), pero esta vez esvisibleViewController ytopViewController sonCONFIGURAR EN NIL!

Una vez que continuamos desde aquí, aparece un mensaje misterioso en la consola del depurador:

Utilizando animación de rotación en dos etapas. Para utilizar una animación de una sola etapa más suave, esta aplicación debe eliminar las implementaciones de métodos de dos etapas.

Misterioso porqueNo estoy usando animación de rotación de dos etapas! NoSegundo medio Las variantes del método están en juego en cualquier lugar en mi código fuente.

Por desgracia, a mi VC consciente de la rotación nunca se le dice que se está produciendo la rotación (incluso si la rotación se produce en la pantalla), por lo que, por supuesto, mi visión se ha ensuciado. Caen el caos y la tristeza. :(

Ni siquiera nos molestaremos en hacer estallar la pila en este punto.

Creo que la documentación de View Controller sugiere el posible problema:

Si desea realizar animaciones personalizadas durante un cambio de orientación, puede hacerlo de dos maneras. Los cambios de orientación solían ocurrir en dos pasos, con notificaciones que se producen en los puntos inicial, medio y final de la rotación. Sin embargo, en iPhone OS 3.0, se agregó soporte para realizar cambios de orientación en un solo paso. El uso de un cambio de orientación de un paso tiende a ser más rápido que el proceso anterior de dos pasos y generalmente se recomienda para cualquier código nuevo.

Me pregunto siMoreNavigationController ¿Sigue respondiendo al proceso de dos pasos y, por lo tanto, está poniendo fin a cualquier intento de usar el proceso de un paso? Tenga en cuenta que, si responde a los mensajes de dos pasos, la variante de un paso no funcionará (nuevamente, según los documentos). No les respondo, pero tengo la sospecha de que algo está detrás de escena.

De hecho, si comento el método de un solo paso y trato de responder awillAnimateSecondHalfOfRotationFromInterfaceOrientation: duración:, YOhacer obtener el memo Pero aún así no se desprende de la pila de forma muy limpia (en términos visuales). Aun mas extrañowillAnimateFirstHalfOfRotationFromInterfaceOrientation: duración: NO se llama, incluso cuando intenté hacer una llamada a mí mismo (usando el mensaje FirstHalf) enshouldAutorotateToInterfaceOrientation:. Vuelve inmediatamente durante un rastreo, como si nunca lo hubiera definido. Suspiro.

Así que esa es la jugada por jugada.

En resumen, tienenadie ¿Se manejó con éxito la rotación del dispositivo en un solo paso para un VC invocado desde el controlador de navegación de más de un controlador de la barra de pestañas? ¡Las mentes inquisitivas quieren saber!

Respuestas a la pregunta(3)

Su respuesta a la pregunta