web-dev-qa-db-fra.com

iOS 6 shouldAutorotate: n'est PAS appelé

J'ai parcouru Internet pour trouver une solution à cela, mais je ne trouve rien. J'essaie de rendre mon application iOS 5 compatible avec iOS 6. Je n'arrive pas à faire fonctionner correctement les trucs d'orientation. Je n'arrive pas à détecter quand une rotation est sur le point de se produire. Voici le code que j'essaie:

- (BOOL)shouldAutorotate {
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
// pre-iOS 6 support
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}

La nouvelle méthode supportedInterfaceOrientation: est appelée très bien. La méthode shouldAutorotate, cependant, ne se déclenchera pas. J'ai besoin de faire un échange d'image lors de la rotation, mais je ne peux obtenir aucune indication qu'une rotation est sur le point de se produire.

Merci d'avance.

48
Lizza

Vérifiez si vous obtenez l'erreur suivante au démarrage de votre application.

Les fenêtres d'application devraient avoir un contrôleur de vue racine à la fin du lancement de l'application

Si tel est le cas, la solution consiste à effectuer la modification suivante dans le AppDelegate.m fichier (bien qu'il semble y avoir un certain nombre de réponses pour résoudre ce problème):

// Replace
[self.window addSubview:[navigationController view]];  //OLD

// With
[self.window setRootViewController:navigationController];  //NEW

Après cela, shouldAutoRotate doit être correctement appelé.

80
user1672376

Lorsque j'utilise UINavigationController comme base pour une application, j'utilise la sous-classe suivante pour me donner la flexibilité de permettre au plus haut viewcontroller enfant de décider de la rotation.

@interface RotationAwareNavigationController : UINavigationController

@end

@implementation RotationAwareNavigationController

-(NSUInteger)supportedInterfaceOrientations {
    UIViewController *top = self.topViewController;
    return top.supportedInterfaceOrientations;
}

-(BOOL)shouldAutorotate {
    UIViewController *top = self.topViewController;
    return [top shouldAutorotate];
}

@end
45
Mike Pollard

Cette méthode n'est pas la bonne façon de déterminer cela. La bonne méthode est willRotateToInterfaceOrientation:duration:

La méthode devrait pivoter vers l'orientation (par opposition à shouldAutorotate) est obsolète et ne sera plus appelée à partir d'iOS 6, mais elle n'était pas censée être utilisée de la même manière que vous l'utilisiez de toute façon.

MODIFIER Réponse aux downvotes répétés. Veuillez expliquer pourquoi l'utilisation de la méthode que j'ai indiquée n'est pas (pour citer OP) "une indication qu'une rotation est sur le point de se produire". Le contenu de la question et le titre ne correspondent pas.

15
borrrden

Si votre viewController est un enfant viewController dans un UINavigationController, vous pouvez effectuer les opérations suivantes:

  • Sous-classe UINavigationController
  • remplacer shouldAutoRotate dans votre sous-classe
  • envoyez votre topViewController ce message lorsque cette méthode est appelée

// Cette méthode se trouve dans votre sous-classe UINavigationController

- (BOOL)shouldAutorotate
{
    if([self.topViewController respondsToSelector:@selector(shouldAutorotate)])
    {
        return [self.topViewController shouldAutorotate];
    }
    return NO;
}
  • Maintenant, vos viewControllers répondront respectivement à cette méthode.
  • Notez que vous pouvez faire de même avec d'autres méthodes d'orinetaion
10
Basheer_CAD

Il semble que sur iOS 6, le contrôleur de navigation des conteneurs ne consulte pas les contrôleurs de vue enfant lors de la rotation:

dans Notes de version iOS 6 :

Désormais, les conteneurs iOS (tels que UINavigationController) ne consultent pas leurs enfants pour déterminer s'ils doivent effectuer une rotation automatique. Par défaut, les orientations d'interface prises en charge par une application et un contrôleur de vue sont définies sur UIInterfaceOrientationMaskAll pour l'idiome iPad et UIInterfaceOrientationMaskAllButUpsideDown pour l'idiome iPhone.

Ce comportement est facile à tester. Ce que j'ai fait, c'est d'utiliser le même contrôleur de vue personnalisé

  1. premier cas comme contrôleur de vue principal
  2. deuxième cas en tant qu'enfant d'un UIPageViewController

Dans le premier cas, tout est décidé dans le contrôleur de navigation personnalisé par la combinaison de shouldAutorotate et supportedInterfaceOrientations étant donné que supportedInterfaceOrientations est d'accord avec les orientations prises en charge de l'application.

Dans le second cas, même si le supportedInterfaceOrientations du contrôleur de vue personnalisé est appelé par l'UIPageViewController, la valeur de retour n'est pas prise en compte. Cela fonctionne si les deux méthodes sont écrasées dans une sous-classe de UIPageViewController. Je ne suis pas sûr des effets secondaires de cela car cette classe n'est pas censée être sous-classée.

10
Adrian

J'utilise iOS 7, mais je pense que mon cas peut être utile aux autres.

J'ai une hiérarchie de contrôleurs de vue approfondie enracinée avec UITabBarController. Le seul endroit où shouldAutorotate est garanti d'être appelé est à l'intérieur de UITabBarController. J'ai donc simplement sous-classe UITabBarController et mis ma logique de contrôle de rotation dans ma méthode shouldAutorotate.

1
Donald

J'obtenais également l'erreur suivante lorsque votre application démarre.

"Les fenêtres d'application devraient avoir un contrôleur de vue racine à la fin du lancement de l'application"

J'utilise un UISplitViewController * splitViewController

Si c'est le cas, le moyen de le corriger consiste à apporter la modification suivante dans le fichier AppDelegate.m:

Remplacer

 [self.window addSubview:[splitViewController view]];

Avec

[self.window setRootViewController:splitViewController];

Après cela, shouldAutoRotate a été appelé et a fonctionné correctement.

1
Michael Jay

C'est comme ça que je le ferais

si vous voulez vérifier quelle est l'orientation actuelle, ajoutez cette ligne à votre fichier viewconrtoller.m

 #define isPortrait [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait || [[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown

puis où vous voulez vérifier l'orientation, écrivez la condition comme ci-dessous

- (void)viewDidLoad
{

        if(isPortrait)
        {
            //portrait mode....

            NSLog(@"its in IsPotraitMode");
        }
        else
        {
            //landscape mode....
            NSLog(@"its in IsLandscapeMode");
        }
}
0
Sam B

Si vous utilisez UINavigationController comme base pour une application. Je crée une catégorie de UINavigationController et je l'appelle "UINavigationController + autoRotate". Mettez ceci dans votre UINavigationController + autoRotate.h:

#import <UIKit/UIKit.h>

@interface UINavigationController (autoRotate)

-(BOOL)shouldAutorotate;
-(NSUInteger)supportedInterfaceOrientations;

@end

Mettez ceci dans UINavigationController + autoRotate.m:

#import "UINavigationController+autoRotate.h"

@implementation UINavigationController (autoRotate)

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

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

@end
0