iphone - objective - Compatibilidad con la orientación de guiones gráficos en Xcode 4.5 e iOS 6.x?
lifecycle viewcontroller ios (2)
He creado dos guiones gráficos idénticos, excepto uno que contiene vistas de retratos y uno que contiene vistas de paisajes.
No quiero utilizar máscaras de autoresize porque el diseño de algunas de las vistas cambia completamente entre vertical y horizontal. He movido manualmente los controles en la vista en el código en el pasado, pero esta vez busqué una forma más fácil :)
La solución más cercana que encontré fue de ''benyboariu'' - ¿ Soporte de orientación de guiones gráficos para xCode 4.2?
Aquí está el código que estoy usando, que funciona bien en iOS 5.x pero no en iOS 6.x.
- (void)updateLandscapeView
{
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (deviceOrientation == UIDeviceOrientationUnknown)
{
if ([[UIScreen mainScreen] bounds].size.height > [[UIScreen mainScreen] bounds].size.width)
{
deviceOrientation = UIDeviceOrientationPortrait;
self.appDelegate.isShowingLandscapeView = NO;
}
else
{
deviceOrientation = UIDeviceOrientationLandscapeLeft;
self.appDelegate.isShowingLandscapeView = YES;
}
}
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !self.appDelegate.isShowingLandscapeView)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard-Landscape" bundle:[NSBundle mainBundle]];
UIViewController * landscape = [storyboard instantiateViewControllerWithIdentifier:@"RootViewController-Landscape"];
self.appDelegate.isShowingLandscapeView = YES;
[UIView transitionWithView:landscape.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
self.view = landscape.view;
} completion:NULL];
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) && self.appDelegate.isShowingLandscapeView)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard-Portrait" bundle:[NSBundle mainBundle]];
UIViewController * portrait = [storyboard instantiateViewControllerWithIdentifier:@"RootViewController"];
self.appDelegate.isShowingLandscapeView = NO;
[UIView transitionWithView:portrait.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
self.view = portrait.view;
} completion:NULL];
}
}
El error que obtengo al depurar en iOS 6.x es:
Aplicación de finalización debido a una excepción no detectada ''UIViewControllerHierarchyInconsistency'', razón: ''¡Una vista solo puede asociarse con un controlador de vista como máximo a la vez! Ver UIView: 0x108276b0; frame = (0 0; 568 268); Autoresize = RM + BM; animations = {position = CABasicAnimation: 0x10815c60; bounds = CABasicAnimation: 0x1082a5e0; }; layer = CALayer: 0x10827710 está asociado con RootViewController: 0x10821f10. Borre esta asociación antes de asociar esta vista con RootViewController: 0x961a150. ''
Normalmente desenlace el controlador de vista de los NIB para corregir este tipo de error, pero no puedo hacer eso con los guiones gráficos.
¿Alguien tiene alguna idea?
Bueno, después de probar todo tipo de formas de intentar solucionar este problema, he encontrado esta solución que funciona en iOS 5.xy 6.x.
Básicamente, el problema parece ser debido al controlador de navegación, por lo tanto, en lugar de hacer
self.view = landscape.view;
o
self.view = portrait.view;
necesita reemplazar todos los controladores de vista contenidos en la pila de controladores de navegación.
Lo que estoy haciendo en el siguiente código es crear un NSMutableArray de todos los controladores de vista en la pila del controlador de navegación. Luego buclee cada controlador de vista y obtenga la etiqueta de vista para determinar qué vista debe reemplazarse. Luego simplemente reemplazo el controlador de vista con la versión horizontal o vertical y luego configuro los controladores de navegación para ver el conjunto de controladores en el arreglo modificado, reemplazando así a todos los controladores de vista.
if (UIDeviceOrientationIsLandscape(deviceOrientation) && !self.appDelegate.isShowingLandscapeView)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard-Landscape" bundle:[NSBundle mainBundle]];
SearchViewController * landscape = [storyboard instantiateViewControllerWithIdentifier:@"SearchViewController-Landscape"];
self.appDelegate.isShowingLandscapeView = YES;
[UIView transitionWithView:landscape.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
NSMutableArray * viewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
if (viewControllers && [viewControllers count] > 0)
{
for (NSUInteger index = 0; index < [viewControllers count]; index++)
{
if ([[[viewControllers objectAtIndex:index] view] tag] == 1000)
{
RootViewController * root = [storyboard instantiateViewControllerWithIdentifier:@"RootViewController-Landscape"];
[viewControllers replaceObjectAtIndex:index withObject:root];
}
else if ([[[viewControllers objectAtIndex:index] view] tag] == 2000)
{
[viewControllers replaceObjectAtIndex:index withObject:landscape];
}
}
[self.navigationController setViewControllers:viewControllers];
}
} completion:NULL];
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) && self.appDelegate.isShowingLandscapeView)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard-Portrait" bundle:[NSBundle mainBundle]];
SearchViewController * portrait = [storyboard instantiateViewControllerWithIdentifier:@"SearchViewController"];
self.appDelegate.isShowingLandscapeView = NO;
[UIView transitionWithView:portrait.view duration:0 options:UIViewAnimationOptionTransitionCrossDissolve|UIViewAnimationCurveEaseIn animations:^{
NSMutableArray * viewControllers = [NSMutableArray arrayWithArray:[self.navigationController viewControllers]];
if (viewControllers && [viewControllers count] > 0)
{
for (NSUInteger index = 0; index < [viewControllers count]; index++)
{
if ([[[viewControllers objectAtIndex:index] view] tag] == 1000)
{
RootViewController * root = [storyboard instantiateViewControllerWithIdentifier:@"RootViewController"];
[viewControllers replaceObjectAtIndex:index withObject:root];
}
else if ([[[viewControllers objectAtIndex:index] view] tag] == 2000)
{
[viewControllers replaceObjectAtIndex:index withObject:portrait];
}
}
[self.navigationController setViewControllers:viewControllers];
}
} completion:NULL];
}
Expandí el código para mostrar cómo funciona esto en vistas anidadas en el controlador de navegación. Si está trabajando en el controlador de vista raíz, obviamente no necesita pasar por todos los controles de vista, simplemente reemplace el controlador de vista en el índice 0.
¡Espero que esto ayude a alguien!
Cambie su controlador de vista portait a una vista normal (sáquelo del controlador de vista). Ahora debería poder instanciarlo como UIView y hacer la transición sin preocuparse de que esté asociado con múltiples controladores de visualización.