iphone - from - load xib swift 4
La forma más fácil de soportar múltiples orientaciones? ¿Cómo cargo un NIB personalizado cuando la aplicación está en Landscape? (5)
Tengo una aplicación en la que me gustaría apoyar múltiples orientaciones. Tengo dos archivos .xib que quiero usar, myViewController.xib y myViewControllerLandscape.xib. myViewController.xib
myViewControllerLandscape.xib. myViewController.xib
existe en project / Resources y myViewControllerLandscape.xib
existe en el directorio raíz del proyecto.
Lo que quiero hacer es usar un NIB separado (myViewControllerLandscape.xib)
para mis rotaciones. Intento detectar la rotación en viewDidLoad l
Esto es así:
if((self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (self.interfaceOrientation == UIInterfaceOrientationLandscapeRight))
{
NSLog(@"Landscape detected!");
[self initWithNibName:@"myViewControllerLandscape" bundle:nil];
}
Pero puedo ver en gdb que esto no se ejecuta cuando la aplicación se inicia con el dispositivo en el paisaje. El mensaje NSLog no se dispara. ¿Por qué es esto? ¿Qué he hecho mal?
Además, si initWithNibName
explícitamente la llamada a la función initWithNibName
en el método viewDidLoad
, esa plumilla no está cargada, y continúa con el archivo myViewController.xib . ¿Qué pasa con mi llamada? ¿Debo especificar un paquete?
¡Gracias!
Encontré una manera mucho mejor que funciona independientemente del controlador de navegación. En este momento, tengo esto funcionando cuando está incrustado en un controlador de navegación, y cuando NO está incrustado (aunque no estoy usando el controlador de navegación ahora mismo, por lo que puede haber algún error que no he visto, por ejemplo, la animación de transición PUSH podría ir gracioso, o algo)
Dos NIB, usando la convención de nomenclatura de Apple. Sospecho que en iOS 6 o 7, Apple podría agregar esto como una "característica". Lo estoy usando en mis aplicaciones y funciona perfectamente:
- los disparadores en WILL girarán, no DEBERÍAN rotar (esperar hasta que el animar de rotación esté a punto de comenzar)
- utiliza la convención de nomenclatura de Apple para los archivos de paisaje / retrato (Default.png es Default-landscape.png si desea que Apple cargue automáticamente una versión apaisada)
- recarga el nuevo NIB
- que restablece
self.view
: esto actualizará AUTOMÁTICAMENTE la pantalla - y luego llama a
viewDidLoad
(Apple NO llamará por esto, si recarga manualmente un NIB)
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if( UIInterfaceOrientationIsLandscape(toInterfaceOrientation) )
{
[[NSBundle mainBundle] loadNibNamed: [NSString stringWithFormat:@"%@-landscape", NSStringFromClass([self class])]
owner: self
options: nil];
[self viewDidLoad];
}
else
{
[[NSBundle mainBundle] loadNibNamed: [NSString stringWithFormat:@"%@", NSStringFromClass([self class])]
owner: self
options: nil];
[self viewDidLoad];
}
}
Me gusta la respuesta aceptada de TechZen, pero como se señala en el comentario de Adam, deja el controlador de vista vertical en la pila de navegación cuando gira hacia el paisaje. Esto significa presionar el botón Atrás en la barra de navegación mientras que en el paisaje llevará al usuario a la vista de retrato. Un compañero de trabajo y yo estamos intentando acercarnos manualmente a la eliminación del elemento adicional de la pila de navegación. Parece que funciona, pero aún tengo muy poca experiencia, así que no hago ninguna promesa. Aquí hay un código de muestra:
Para pasar de vertical a horizontal:
[[self navigationController] pushViewController:landscapeViewController animated:NO];
[self removeFromNavigationStack:[MyPortraitViewController class]];
Para volver al retrato:
[[self navigationController] pushViewController:portraitViewController animated:NO];
[self removeFromNavigationStack:[MyLandscapeViewController class]];
Si no usa animación: NO, puede recibir advertencias sobre el estado de la navegación.
Ayudante:
- (void)removeFromNavigationStack:(Class)oldClass {
UINavigationController *nav = [self navigationController];
NSMutableArray *newStack = [NSMutableArray array];
for (UIViewController *vc in nav.viewControllers) {
if (![vc isMemberOfClass:[oldClass class]]) {
[newStack addObject: vc];
}
[nav setViewControllers:newStack animated:NO];
}
Realmente me gusta la respuesta de Adam: la modifiqué ligeramente para permitir la carga inicial del plumín en el retrato o el paisaje
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if( !nibNameOrNil ) nibNameOrNil = [self nibNameRotated:[[UIApplication sharedApplication] statusBarOrientation]];
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
return self;
}
- (NSString*) nibNameRotated:(UIInterfaceOrientation)orientation
{
if( UIInterfaceOrientationIsLandscape(orientation)) return [NSString stringWithFormat:@"%@-landscape", NSStringFromClass([self class])];
return [NSString stringWithFormat:@"%@", NSStringFromClass([self class])];
}
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
NSString *nibname = [self nibNameRotated:toInterfaceOrientation];
[[NSBundle mainBundle] loadNibNamed:nibname owner:self options:nil];
[self viewDidLoad];
}
Tienes que cargar una vista, luego verificar la orientación y cargar otra si es necesario. Verifique la orientación en shouldAutorotateToInterfaceOrientation:
devuelve yes si desea rotar.
Uso un controlador de navegación para gestionar la transición. Si tengo la vista de retrato hacia arriba y el dispositivo gira, presiono la vista de paisaje y luego aparece la vista de paisaje cuando vuelve al retrato.
Editar:
Devuelvo SÍ para todas las orientaciones en shouldAutorotateToInterfaceOrientation: ¿se ejecutará cuando se inicie la aplicación? ¿Empuja su vista dentro de esta función?
Las constantes de orientación no son globales que consulta, sino que forman parte de los mensajes enviados por el sistema al controlador. Como tal, no puede detectar fácilmente la orientación antes de que se cargue un controlador de vista. En cambio, conectó la aplicación para comenzar en una orientación particular (generalmente retrato) y luego gira inmediatamente. (Consulte Safari móvil. Siempre comienza en vertical y luego gira a horizontal).
Estos son los dos métodos que utilicé para cambiar mis vistas de retrato y paisaje.
Los tres controladores de vista tienen este método:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
El retrato tiene esto:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (toInterfaceOrientation==UIInterfaceOrientationLandscapeRight) {
[self.nav pushViewController:rightLVC animated:NO];
}
if (toInterfaceOrientation==UIInterfaceOrientationLandscapeLeft) {
[self.nav pushViewController:leftLVC animated:NO];
}
}
Cada controlador de paisaje tiene esto:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if (toInterfaceOrientation==UIInterfaceOrientationPortrait) {
[self.nav popViewControllerAnimated:NO];
}
La aplicación comienza en retrato. Si la orientación del dispositivo es horizontal, empuja los paisajes apropiados. Cuando el dispositivo gira de nuevo a retrato, aparece el paisaje. Para el usuario, parece que la misma vista se reorganiza para una orientación diferente.
Una opción más, TPMultiLayoutViewController .