2011-10-25 10 views
7

Fondo & Objetivo: Tengo una aplicación para iPad basada en UISplitViewController, hasta ahora admitía 4 orientaciones, pero ahora quiero bloquearla solo en horizontal. Cambié shouldAutorotateToInterfaceOrientation del controlador de vista izquierda para admitir solo el modo de paisaje, pero esto impide que se llame a viewWillAppear.ViewWillAppear no se llama con UISplitViewController

Detalles: Mis controladores de vista de protectores y se organizan de la siguiente manera:

window 
`-- splitVC (UISplitViewController) 
    `-- rootNav (UINavigationController) 
     `-- hvc (HostManagerViewController, derived from UIViewController) 
    `-- detailViewController (DetailViewController, derived from UIViewController) 

Esto se implementa en la App Delegado de la siguiente manera:

- (BOOL)application:(UIApplication *)application 
     didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 
    HostManagerViewController *hvc = [[[HostManagerViewController alloc] 
             initWithNibName:nil bundle:nil] autorelease]; 
    self.detailViewController = [[[DetailViewController alloc] 
           initWithNibName:nil bundle:nil] autorelease]; 
    UINavigationController *rootNav = [[[UINavigationController alloc] 
             initWithRootViewController:hvc] autorelease]; 
    UISplitViewController *splitVC= [[[UISplitViewController alloc] init] autorelease]; 
    [splitVC setViewControllers:[NSArray arrayWithObjects:rootNav, 
           detailViewController, nil]]; 

    splitVC.delegate = detailViewController; 
    [window addSubview:splitVC.view]; 
    [window setRootViewController:splitVC]; 
    return YES; 
} 

viewWillAppear se llama cuando tanto DetailViewController.m y HostManagerViewController.m contienen

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return YES; 
} 
Console output: 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 3 
Hostmanager: Viewdidload 
Should rotate called to hostmanager with 1 
Hostmanager: viewwillappear 

Pero cuando cambio 'código de s a

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return (UIInterfaceOrientationIsLandscape(interfaceOrientation)); 
} 

luego' HostManagerViewController viewWillAppear` de HostManagerViewController no se invoca. salida de la consola

Should rotate called to hostmanager with 1 (1 is the numeric value of interfaceOrientation) 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 3 
Should rotate called to hostmanager with 3 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 3 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 3 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 1 
Should rotate called to hostmanager with 3 
Hostmanager: Viewdidload 
Should rotate called to hostmanager with 1 

Sólo los modos horizontal están soportados en el Info.plist

EDIT: mensajes insertados NSLog para realizar un seguimiento shouldAutorotateToInterfaceOrientation, viewWillAppear y ViewDidLoad

+0

¿es posible que cargue una muestra de este proyecto? – ACBurk

+0

¿con qué versión de iOS está ejecutando esto? – ACBurk

+0

Estoy usando 4.3. Se puede reducir a un testcase más pequeño. ¿Dónde lo cargo entonces? –

Respuesta

8

Pregunté qué versión de IOS que estaba utilizando porque he intentado crear una simple reproducción de su problema y encontré el el comportamiento difiere entre 4.3 y 5.0.Realmente hace todas las llamadas correctas en 5.0. Creo que esto es simplemente un error con UISplitviewController. El controlador de Splitview estaba bastante lleno de errores. La respuesta de aopsfan no resuelve el problema (lo he confirmado). Yo sugeriría uisplitviewcontroller subclases, y anulando viewWillAppear del controlador SplitView, viewdidappear así:

#import "testSplitViewController.h" 

@implementation testSplitViewController 

-(void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 

    NSString *reqSysVer = @"5.0"; 
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion]; 
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending) 
     [[[self viewControllers] objectAtIndex:0] viewWillAppear:animated]; 
} 

-(void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated]; 

    NSString *reqSysVer = @"5.0"; 
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion]; 
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] == NSOrderedAscending) 
     [[[self viewControllers] objectAtIndex:0] viewDidAppear:animated]; 
} 
@end 

usted tiene que comprobar el número de versión de modo que usted no hace la llamada viewDidAppear dos veces.

O simplemente vaya con 5.0 o superior si puede, ya que el error parece ser solucionado.

+0

¡Sí, sí y sí! Parece que hay un error en el controlador de vista dividida, por lo que forzar 'viewWillAppear' en las vistas secundarias desde la vista dividida parece ser la solución. Muchas gracias, @ACBurk –

+0

¿Existe alguna forma más genérica que las verificaciones de versión antes de llamar a 'viewDidAppear'? Hay 'isViewLoaded', pero ¿hay también un tipo de llamada' hasViewAppeared'? –

+0

No es que lo sepa, pero lo investigaré – ACBurk

3

Básicamente, ya que un UISplitViewController tiene dos partes, es necesario una implementación universal de shouldAutorotate. Supongo que abordar la rotación de los controles de visualización individualmente puede causar algunos efectos secundarios extraños, aunque tenga en cuenta que no pude replicar su problema viewWillAppear, por lo que esta solución es realmente una suposición.

Recomendaría hacer una subclase dead-simple de UISplitViewController. El nombre de "SplitViewController", y en ella es .m archivo, eliminar todo excepto shouldAutorotate, que se verá así:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return (UIInterfaceOrientationIsLandscape(interfaceOrientation)); 
} 

Ahora cambie su código shouldAutorotate en HostManagerViewController y DetailViewController de nuevo a:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 
    return YES; 
} 

Ahora , en su delegado de aplicación, use esta clase en lugar de UISplitViewController. Esto debería (puede) solucionar su problema.

+0

También estoy de acuerdo con aopsfan, no debe bloquear esto en cada controlador de vista, debe bloquearlo en el controlador raíz (UISplitViewController en su caso). – alinoz

+0

+1 Gracias por sugerir esto. Lamentablemente, no resolvió el problema –

0

se establece el delegado de la UISplitViewControler a la detailViewController

splitVC.delegate = detailViewController; 

Creo que el mejor lugar para bloquear las rotaciones estará en el DetailViewController y no en el HostManagerViewController. Me gustaría cambiar el - shouldAutorotateToInterfaceOrientation en el HostManagerViewController para volver Allways SI y en el DetailViewController yo añadiría:

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    return (UIInterfaceOrientationIsLandscape == interfaceOrientation); 
} 
Cuestiones relacionadas