2011-10-25 4 views
7

Contexte & Objectif: J'ai une application iPad basée sur UISplitViewController - jusqu'à présent, elle supportait 4 orientations mais maintenant je veux la verrouiller uniquement en mode paysage. J'ai changé shouldAutorotateToInterfaceOrientation du contrôleur de vue gauche pour prendre en charge uniquement le mode paysage, mais cela empêche son viewWillAppear d'être appelé.ViewWillAppear ne se fait pas appeler avec UISplitViewController

Détails: Mes contrôleurs de vue iPad sont organisés comme suit:

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

Ceci est mis en œuvre dans le délégué App comme ci-dessous:

- (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 est appelée lorsque les deux DetailViewController.m et HostManagerViewController.m contiennent

- (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 

Mais quand je change 'le code de la

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

puis' HostManagerViewController viewWillAppear` de HostManagerViewController n'est pas invoqué. Sortie de la console

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 

Seuls les modes Paysage sont pris en charge dans le Info.plist

EDIT: messages Inséré NSLog pour suivre shouldAutorotateToInterfaceOrientation, viewWillAppear et ViewDidLoad

+0

est-il possible pour vous de télécharger un échantillon de ce projet? – ACBurk

+0

quelle version iOS utilisez-vous? – ACBurk

+0

J'utilise 4.3. Le réduire à un plus petit testcase peut être fait. Où puis-je le télécharger ensuite? –

Répondre

8

J'ai demandé quelle version iOS que vous utilisiez parce que j'essayé de créer une simple reproduction de votre problème et trouvé la le comportement diffère entre 4.3 et 5.0.Il fait effectivement tous les appels corrects dans 5.0. Je crois que c'est simplement un bogue avec UISplitviewController. Contrôleur Splitview était tout à fait buggy. La réponse d'Aopsfan ne résout pas le problème (je l'ai confirmé). Je suggère subclassing uisplitviewcontroller, et en remplaçant la viewWillAppear du contrôleur SPLITVIEW, viewdidappear comme ceci:

#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 

Vous devez vérifier le numéro de version de sorte que vous ne faites pas deux fois l'appel viewDidAppear.

Ou tout simplement aller avec 5.0 ou plus si vous le pouvez, puisque le bug semble être corrigé.

+0

Oui, oui et oui! Il semble y avoir un bug dans le contrôleur de vue divisée - donc forcer 'viewWillAppear' sur les vues enfants de la vue partagée semble être la solution de contournement. Merci beaucoup, @ACBurk –

+0

Existe-t-il un moyen plus générique que les vérifications de version avant d'appeler 'viewDidAppear'? Il y a 'isViewLoaded', mais y at-il aussi un type d'appel' hasViewAppeared'? –

+0

Ce que je ne connais pas du haut de ma tête, mais je vais regarder dans – ACBurk

3

En fait, depuis un UISplitViewController a deux parties, vous avez besoin une implémentation universelle de shouldAutorotate. Je suppose que s'attaquer à la rotation des contrôleurs de vue individuellement peut causer des effets secondaires bizarres - mais s'il vous plaît prendre note que je n'ai pas été en mesure de répliquer votre problème viewWillAppear, donc cette solution est vraiment une supposition.

Je recommanderais de faire une sous-classe morte-simple de UISplitViewController. Nommez "SplitViewController", et dans son fichier .m, supprimer tout sauf shouldAutorotate, qui ressemblera à ceci:

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

changer maintenant votre code shouldAutorotate dans HostManagerViewController et DetailViewController Retour à:

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

maintenant , dans le délégué de votre application, utilisez cette classe au lieu de UISplitViewController. Cela devrait (peut-être) résoudre votre problème.

+0

Je suis également d'accord avec Aopsfan, vous ne devriez pas bloquer cela sur chaque contrôleur de vue, vous devez le bloquer dans le contrôleur racine (UISplitViewController dans votre cas). – alinoz

+0

+1 Merci d'avoir suggéré ça. Malheureusement, il n'a pas résolu le problème –

0

Vous définissez le délégué du UISplitViewControler au detailViewController

splitVC.delegate = detailViewController; 

Je pense que le meilleur endroit pour bloquer les rotations seront dans le DetailViewController et non dans le HostManagerViewController. Je changerais la - shouldAutorotateToInterfaceOrientation dans le HostManagerViewController revenir AllWays OUI et dans le DetailViewController je voudrais ajouter:

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