iOS5 rompe las devoluciones de llamada de rotación UISplitViewController, cómo invocar manualmente?
rotation (1)
No sé la forma correcta de manejar esta situación. Sin embargo, lo siguiente parece funcionar para mí en iOS 5.
En
splitViewController:willHideViewController:withBarButtonItem:forPopoverController:
almacena una referencia al barButtonItem en algo comoself.barButtonItem
. Mueva el código para mostrar el botón en un método diferente, digaShowRootPopoverButtonItem
.En
splitViewController:willShowViewController:invalidatingBarButtonItem:
borre esa referencia de referencia deself.barButtonItem
. Mueva el código para mostrar el botón en un método diferente, digaInvalidateRootPopoverButtonItem
.En
viewWillLayoutSubviews
, muestre u oculte manualmente el botón, según la orientación de la interfaz
Aquí está mi implementación de viewWillLayoutSubviews
. Tenga en cuenta que llamar a self.interfaceOrientation
siempre devuelve portrait, de ahí mi uso de statusBarOrientation
.
- (void)viewWillLayoutSubviews
{
if (UIInterfaceOrientationIsPortrait(
[UIApplication sharedApplication].statusBarOrientation))
{
[self ShowRootPopoverButtonItem:self.barButtonItem];
}
else
{
[self InvalidateRootPopoverButtonItem:self.barButtonItem];
}
}
Como se informó en otras preguntas aquí en SO, iOS 5 cambia cómo se envían las devoluciones de llamadas de rotación para los controladores de vista dividida según esta nota de publicación. Esto no es una tontería (creo), ya que no puedo encontrar otra pregunta sobre SO que trate sobre cómo ajustar el uso del controlador de vista dividida en iOS 5 para hacer frente al cambio:
Las devoluciones de llamadas de rotación en iOS 5 no se aplican para ver los controladores que se presentan en una pantalla completa. Lo que esto significa es que si su código presenta un controlador de vista sobre otro controlador de vista, y luego el usuario gira el dispositivo a una orientación diferente, al momento del rechazo, el controlador subyacente (es decir, el controlador que presenta) no recibirá ninguna devolución de llamada de rotación. Sin embargo, tenga en cuenta que el controlador que se presenta recibirá una llamada a viewWillLayoutSubviews cuando se vuelva a mostrar, y la propiedad interfaceOrientation se puede consultar desde este método y se puede usar para diseñar el controlador correctamente.
Tengo problemas para configurar el botón Popover en mi controlador de vista dividida raíz (el que se supone que muestra la vista del panel izquierdo en un popover cuando estás en retrato). Así es como la secuencia de inicio de mi aplicación solía funcionar en iOS 4.x cuando el dispositivo está en modo apaisado:
Instale el controlador de vista dividida en la ventana con
[window addSubview:splitViewController.view]; [window makeKeyAndVisible];
[window addSubview:splitViewController.view]; [window makeKeyAndVisible];
. Esto da como resultadosplitViewController:willHideViewController:withBarButtonItem:forPopoverController:
se llama al delegado (es decir, simula un paisaje -> rotación de retrato) aunque el dispositivo ya esté en modo apaisado.Presente un modo de pantalla completa (mi pantalla de carga) que cubre por completo la vista dividida debajo.
Finaliza la carga y cierra la pantalla de carga modal. Como el dispositivo está en modo horizontal, cuando se revela el controlador de vista dividida, esto hace que
splitViewController:willShowViewController:invalidatingBarButtonItem:
se llame al delegado (es decir, simulando un retrato -> rotación horizontal), invalidando así el elemento del botón de barra, eliminándolo desde el lado derecho de la vista dividida, y dejándonos donde queremos estar. ¡Hurra!
Entonces, el problema es que debido al cambio descrito en esa nota de lanzamiento, cualquier cosa que ocurra internamente en iOS 4.3 que resulte en splitViewController:willShowViewController:invalidatingBarButtonItem:
ser llamado ya no ocurre en iOS 5. Intenté subclasificar UISplitViewController para poder proporcionar una versión personalizada implementación de viewWillLayoutSubviews
como lo sugiere la nota de lanzamiento, pero no sé cómo reproducir la secuencia deseada de eventos internos que desencadena iOS 4. Intenté esto:
- (void) viewWillLayoutSubviews
{
[super viewWillLayoutSubviews];
UINavigationController *rightStack = [[self viewControllers] objectAtIndex:1];
UIViewController *rightRoot = [[rightStack viewControllers] objectAtIndex:0];
BOOL rightRootHasButton = ... // determine if bar button item for portrait mode is there
// iOS 4 never goes inside this ''if'' branch
if (UIInterfaceOrientationIsLandscape( [self interfaceOrientation] ) &&
rightRootHasButton)
{
// Manually invoke the delegate method to hide the popover bar button item
[self.delegate splitViewController:self
willShowViewController:[[self viewControllers] objectAtIndex:0]
invalidatingBarButtonItem:rightRoot.navigationItem.leftBarButtonItem];
}
}
Esto funciona principalmente, pero no al 100%. El problema es que invocar el método de delegado usted mismo no invalida realmente el elemento del botón de barra, por lo que la primera vez que gira a vertical, el sistema cree que el elemento del botón de barra todavía está instalado correctamente y no intenta volver a instalarlo. Solo después de rotar de nuevo a horizontal y luego de vuelta a retrato, el sistema ha vuelto al estado correcto y realmente instalará el elemento del botón de la barra popover en modo vertical.
En función de esta pregunta , también intenté invocar todas las devoluciones de llamadas de forma manual en lugar de activar el método de delegado, por ejemplo:
// iOS 4 never goes inside this ''if'' branch
if (UIInterfaceOrientationIsLandscape( [self interfaceOrientation] ) &&
rightRootHasButton)
{
[self willRotateToInterfaceOrientation:self.interfaceOrientation duration:0];
[self willAnimateRotationToInterfaceOrientation:self.interfaceOrientation duration:0];
[self didRotateFromInterfaceOrientation:self.interfaceOrientation];
}
Sin embargo, esto parece causar un bucle infinito en viewWillLayoutSubviews
:(
¿Alguien sabe cuál es la forma correcta de simular los eventos de rotación estilo iOS4 para un controlador de vista dividida que aparece detrás de un modal de pantalla completa? ¿O no debería simularlos y hay otro enfoque de mejores prácticas que se ha convertido en el estándar para iOS5?
Cualquier ayuda realmente apreciada ya que este problema nos impide presentar nuestra versión de corrección de errores de iOS5 en la tienda de aplicaciones.