62 votes

shouldAutorotateToInterfaceOrientation n'étant pas appelé dans iOS 6

J'utilise MGSplitViewController et j'utilise shouldAutorotateToInterfaceOrientation pour contrôler la taille du contrôleur de vue principal en rotation.

Tout fonctionne bien sur iOS 5, mais sur iOS 6 (simulateur et iPad), shouldAutorotateToInterfaceOrientation n'est jamais appelé.

Est-ce un bug que je devrais m'attendre à résoudre avec la version finale d'iOS 6 ou dont quelque chose dont je ne suis pas au courant a changé?

128voto

BootMaker Points 359

VEUILLEZ la LIRE ATTENTIVEMENT, ou vous pourriez perdre de 1 à 2 jours de votre vie avec l'écrou et de la lutte contre la secouant, en tournant le dispositif de test comme le chimpanzé du zoo, qui a attrapé un visiteur mobile! Tôt ou tard...promis :)

DANS iOS 6

shouldAutorotateToInterfaceOrientation:

est obsolète et remplacé par

shouldAutorotate

cela signifie iOS 6 ne jamais appeler shouldAutorotateToInterfaceOrientation:

donc, si vous avez utilisé les éléments suivants dans votre demande

AVANT iOS6 (iOS5,iOS4, etc.)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (interfaceOrientation == UIInterfaceOrientationPortrait) {
// your code for portrait mode

}

return YES;
}

vous devez utiliser

APRÈS iOS 6+

- (BOOL)shouldAutorotate {

UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];

if (orientation == UIInterfaceOrientationPortrait) {
// your code for portrait mode

}

return YES;
}

ÊTRE CONSCIENT

UIInterfaceOrientation est une propriété de UIApplication et ne contient que 4 possibilités qui correspondent à l'orientation de la barre d'état:

UIInterfaceOrientationPortrait = UIDeviceOrientationPortrait,

UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,

UIInterfaceOrientationLandscapeLeft = UIDeviceOrientationLandscapeRight,

UIInterfaceOrientationLandscapeRight = UIDeviceOrientationLandscapeLeft

NE PAS CONFONDRE AVEC

UIDeviceOrientation qui est une propriété de la UIDevice classe, et contient 7 valeurs possibles:

UIDeviceOrientationUnknown - Can not be determined

UIDeviceOrientationPortrait - Home button facing down

UIDeviceOrientationPortraitUpsideDown - Home button facing up

UIDeviceOrientationLandscapeLeft - Home button facing right

UIDeviceOrientationLandscapeRight - Home button facing left

UIDeviceOrientationFaceUp - Device is flat, with screen facing up

UIDeviceOrientationFaceDown - Device is flat, with screen facing down

vous pouvez même les utiliser théoriquement UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; qui retourne UIDeviceOrientation - l'appareil réelle orientation - MAIS vous devez savoir que UIDeviceOrientation n'est pas toujours égale UIInterfaceOrientation!!! Par exemple, lorsque votre appareil est sur une simple table, vous pouvez recevoir la valeur inattendue.

Vous pouvez utiliser UIInterfaceOrientation orientation = auto.interfaceOrientation; trop qui renvoie UIInterfaceOrientation, l'orientation actuelle de l'interface, MAIS c'est une propriété de UIViewController, de sorte que vous pouvez accéder à celui-ci seulement dans UIViewController classes.

Si vous souhaitez soutenir à la fois avant iOS6 (iOS3/4/5) et iOS6 périphériques - qui pourrait être évidente - il suffit d'utiliser les deux shouldAutorotateToInterfaceOrientation: et shouldAutorotate dans votre code.

À partir d'iOS 6 il y a 3 niveaux et 3 mesures que le dispositif de contrôle pendant le lancement de l'app, vous devez contrôler si vous le souhaitez.

1. Info.plist - Supported Interface Orientations

que vous pourriez graphiquement dans l'onglet Résumé. La séquence de permis à des orientations est IMPORTANT, que vous pouvez modifier manuellement par l'édition de l'info.plist, et l'appareil va choisir la première lorsque l'application est lancé! C'est critique car le problème est toujours le lancement de l'app quand il y a le risque que le [UIDevice currentDevice].l'orientation est inconnu, surtout quand nous de tester notre application sur une surface plane.

plist setting in XCode (Info)

ÊTRE CONSCIENT Il y a deux autres paramètres de possibilité avec (iPad) ou (iPhone) extension, si vous utilisez l'un d'entre eux, il va utiliser le réglage de l'appareil ou de simulateur et de négliger les paramètres généraux sans l'extension. Donc, si vous exécutez un iPhone seule application et accidentellement vous avez quitté une "prise en charge de l'Interface Orientations (iPad)" la ligne quelque part dans le plist même sans données, il va négliger les règles que vous avez créé plus tôt dans les paramètres généraux (dans mon exemple pour l'iPhone) et vous pourriez obtenir un rejet de votre Application avec un texte "Nous avons constaté que votre application ne répond pas aux exigences pour la course sur iPad...", même si votre application n'a pas l'intention d'utiliser une orientation sur l'iPhone, mais l'iPad va l'utiliser ce qui pourrait provoquer des erreurs imprévisibles, comme toutes les applications de l'iPhone à exécuter sur iPad pendant le processus de soumission.

2. AppDelegate - application:supportedInterfaceOrientationsForWindow

retour d'un masque de bits liste de toutes les orientations que vous souhaitez autoriser, de façon à remplacer l'info.plist paramètres.C'est convoquée au moins une fois chaque fois que l'appareil tourne.

3. Top-level view controller or RootViewController - supportedInterfaceOrientations

ce qui donne une intersection avec l'ensemble de l'app et app délégué, qui a pas un zéro pour éviter le crash. C'est convoquée au moins une fois chaque fois que l'appareil tourne, sauf il y a une autre méthode installé dans notre contrôleur:

shouldAutorotate

ce qui interfère avec l'app permis orientations, et donne un BOOLÉEN par défaut OUI.

BE CAREFUL when you use NavigationController

comme le premier contrôleur dans votre AppDelegate, comme ceci:

DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
UINavigationController *navigationController=[[UINavigationController alloc] initWithRootViewController:detailViewController];
self.window.rootViewController =nil;
self.window.rootViewController = navigationController;
[self.window makeKeyAndVisible];
return YES;

dans ce cas, vous devez placer le code suivant dans votre AppDelegate comme une catégorie d'attachement à NavigationController classe, comme c'est le premier contrôleur, et si vous n'avez pas fait une sous-catégorie, vous n'avez pas de place/code où vous pouvez configurer ses paramètres d'orientation, de sorte que vous besoin de forcer pour vérifier votre véritable rootViewController dans ce cas, le detailViewController pour les orientations:

@implementation UINavigationController (OrientationSettings_IOS6)

-(BOOL)shouldAutorotate {
return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations {
return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

@end

après cela, vous pouvez définir les orientations privilégiées dans votre "niveau supérieur" ViewController (dans mon exemple c'est le detailViewController) avec l'une des méthodes que vous avez disponible dans iOS 6 pour ViewControllers, comme ci-dessous:

1. (BOOL)shouldAutorotate

2. (NSUInteger)supportedInterfaceOrientations

3. (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation

55voto

Rocotilos Points 2341

Ok, je l'ai eu à travailler dans iOS6 iPad Simulateur. Yay. Voici ce que j'ai fait:

Je viens de vous montrer avant et après, il doit être auto-explicatif:

AVANT

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

if (interfaceOrientation==UIInterfaceOrientationPortrait) {
 // do some sh!t

}

return YES;
}

APRÈS

- (BOOL)shouldAutorotate {

UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];

if (orientation==UIInterfaceOrientationPortrait) {
 // do some sh!t

}

return YES;
}

Comme pour les prises en charge de l'orientation, vous pouvez spécifier dans l'info.plist en tant que tel: Supported Orientation pic

Ou utilisez le code:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait; // etc
}

Edit: À la réflexion, si vous prévoyez de soutien versions inférieures (iOS4.3/5/5.1) ainsi que 6.0 alors il suffit d'inclure les deux méthodes avec le même code de contenu. Fonctionne pour moi (en sim de toute façon)

20voto

David Neil Wilson Points 327

Paramétrer le contrôleur de route de la fenêtre de l'application plutôt que d'ajouter simplement sa vue comme une sous-vue fonctionnait pour moi (comme le faisait Rocotilos)

 //    [self.window addSubview:self.topLevelNavigationController.view];
self.window.rootViewController = self.topLevelNavigationController;
 

18voto

user441669 Points 608

Voici une solution pour iOS 5 et le code antérieur ne nécessitant pas la duplication de votre logique. Il suffit d’ajouter ce code à votre contrôleur de vue pour qu’il génère les éléments supportedInterfaceOrientations à partir de votre méthode shouldAutorotateToInterfaceOrientation existante.

 -(BOOL)shouldAutorotate{
    return YES;
}

-(NSInteger)supportedInterfaceOrientations{
NSInteger mask = 0;
if ([self shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationLandscapeRight])
    mask |= UIInterfaceOrientationMaskLandscapeRight;
if ([self shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationLandscapeLeft])
    mask |= UIInterfaceOrientationMaskLandscapeLeft;
if ([self shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationPortrait])
    mask |= UIInterfaceOrientationMaskPortrait;
if ([self shouldAutorotateToInterfaceOrientation: UIInterfaceOrientationPortraitUpsideDown])
    mask |= UIInterfaceOrientationMaskPortraitUpsideDown;
return mask;
}
 

15voto

g1de0n_ph Points 151

Une solution rapide pour moi a été d'ajouter ce code sur mon contrôleur de vue racine

 - (BOOL)shouldAutorotate {
    return [self shouldAutorotateToInterfaceOrientation:self.interfaceOrientation];
}
 

De cette façon, j'utilise toujours la même logique que celle utilisée pour les versions antérieures à iOS 6. Bien entendu, j'avais initialement défini mon rootViewController dans les délégués de mon application correctement, au lieu de simplement ajouter aux sous-vues de Windows.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X