web-dev-qa-db-fra.com

iOS6: supportedInterfaceOrientations ne fonctionne pas (est invoqué mais l'interface continue à pivoter)

Dans mon application, j'ai plusieurs vues, certaines vues doivent prendre en charge à la fois les modes portrait et paysage, tandis que d'autres doivent uniquement prendre en charge les portraits. Ainsi, dans le résumé du projet, j'ai tous sélectionné toutes les orientations.

Le code ci-dessous permet de désactiver le mode paysage sur un contrôleur de vue antérieur à iOS 6:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

Comme shouldAutorotateToInterfaceOrientation était obsolète dans iOS6, j'ai remplacé ce qui précède par:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMask.Portrait;
}

Cette méthode est correctement appelée lorsque la vue apparaît (je peux définir un point d'arrêt pour s'en assurer), mais l'interface passe toujours en mode paysage, même si je ne renvoie le masque que pour les modes portrait. Qu'est-ce que je fais mal?

Il semble qu’il soit actuellement impossible de créer une application ayant différentes exigences d’orientation par vue. Il semble ne respecter que les orientations spécifiées dans le résumé du projet.

50
aneuryzm

Si vous utilisez UINavigationController en tant que contrôleur de fenêtre racine, c'est itsshouldAutorotate & supportedInterfaceOrientations qui sera appelé.

Idem si vous utilisez un UITabBarController, etc.

Il faut donc sous-classer votre contrôleur de navigation/tabulation et remplacer ses méthodes shouldAutorotate & supportedInterfaceOrientations.

69
Martin

essayez de changer ce code dans AppDelegate.m

//   self.window.rootViewController = self.navigationController;

    [window setRootViewController:navigationController];

c'est la réponse complète

shouldAutorotateToInterfaceOrientation n'étant pas appelé dans iOS 6

XD

30
NSStudent

Dans mon cas, j'ai UINavigationController et mon contrôleur de vue à l'intérieur. J'ai dû sous-classer UINavigationController et, pour ne prendre en charge que Portrait, ajouter cette méthode:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}

Ainsi, dans la sous-classe UINavigationController, je dois vérifier quelle orientation est prise en charge par le topViewController actuel.

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

Une chose que j’ai trouvée est que si vous avez une vieille application qui est toujours en cours

[window addSubView:viewcontroller.view];  //This is bad in so may ways but I see it all the time...

Vous devrez mettre à jour cela pour:

[window setRootViewController:viewcontroller]; //since iOS 4

Une fois que vous faites cela, l'orientation devrait recommencer à fonctionner.

15
James Jones

L'équipe de Ray Wenderlich - http://www.raywenderlich.com/ indique la meilleure solution pour iOS6 dans "iOS6 By Tutorials" - et est préférable à la sous-classification de UINavigationController dans la plupart des cas.

J'utilise iOS6 avec un scénarimage qui inclut un contrôleur UINavigationController en tant que contrôleur de vue initial.

//AppDelegate.m - cette méthode n'est pas disponible avant iOS6 malheureusement

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;

if(self.window.rootViewController){
    UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
    orientations = [presentedViewController supportedInterfaceOrientations];
}

return orientations;
}

//MyViewController.m - renvoie toutes les orientations que vous souhaitez prendre en charge pour chaque UIViewController

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}
14
Phil

Comme l'ont indiqué d'autres personnes, si vous utilisez un UINavigationController et souhaitez personnaliser différentes vues, vous souhaiterez sous-classer UINavigationController et vous assurer de disposer de ces deux composants:

@implementation CustomNavigationController

// -------------------------------------------------------------------------------
//  supportedInterfaceOrientations:
//  Overridden to return the supportedInterfaceOrientations of the view controller
//  at the top of the navigation stack.
//  By default, UIViewController (and thus, UINavigationController) always returns
//  UIInterfaceOrientationMaskAllButUpsideDown when the app is run on an iPhone.
// -------------------------------------------------------------------------------
- (NSUInteger)supportedInterfaceOrientations
{
    return [self.topViewController supportedInterfaceOrientations]; 
}

// -------------------------------------------------------------------------------
//  shouldAutorotate
//  Overridden to return the shouldAutorotate value of the view controller
//  at the top of the navigation stack.
//  By default, UIViewController (and thus, UINavigationController) always returns
//  YES when the app is run on an iPhone.
// -------------------------------------------------------------------------------
- (BOOL)shouldAutorotate
{
    return [self.topViewController shouldAutorotate];
}

Ensuite, dans toute vue représentant uniquement un portrait, vous devez inclure:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

Et dans tous les cas, tout est à l’envers:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAllButUpsideDown;
}
10
Causaelity

Fondamentalement, comme quelqu'un l'a dit ci-dessus, mais plus en détail:

  1. Créer un nouveau fichier qui est une sous-classe de UINavigationController
  2. Accédez à votre scénario, puis cliquez sur le contrôleur de navigation, définissez sa classe sur celle que vous venez de créer.
  3. Dans cette classe (fichier .m), ajoutez le code suivant pour qu'il reste en mode portrait:

    (BOOL)shouldAutorotate
    {
      return NO;
    } 
    
    (NSUInteger)supportedInterfaceOrientations
    {
     return UIInterfaceOrientationMaskPortrait;
    }
    

Cela a fonctionné pour moi

2
user1601259

La meilleure façon, selon moi, est de créer une catégorie plutôt que de sous-classer UINavigationController ou UITabbarController

votre UINavigationController + Rotation.h

#import <UIKit/UIKit.h>

@interface UINavigationController (Rotation)

@end

votre UINavigationController + Rotation.m

#import "UINavigationController+Rotation.h"

@implementation UINavigationController (Rotation)

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

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

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


@end

Essayez de faire en sorte que tous vos contrôleurs importent cette catégorie et fonctionnent comme un charme. Vous pouvez même empêcher un contrôleur de tourner et appuyer sur un autre contrôleur qui tourne.

1
Vassily

Ce code a fonctionné pour moi:

-(BOOL)shouldAutorotate {
     return YES;
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll;
}

Orientation des applications iPhone/iPad découvrez ma propre réponse

1
tcd

Les réponses ici m'ont orienté dans la bonne direction bien que je ne pouvais pas le faire fonctionner simplement en copier/coller parce que j'utilise UINavigationControllers à l'intérieur d'un UITabBarController. Donc, ma version dans AppDelegate.m ressemble à ceci, ce qui fonctionnera pour UITabBarControllers, UINavigationControllers ou UINavigationControllers dans un UITabBarController. Si vous utilisez d'autres contrôleurs de confinement personnalisés, vous devrez les ajouter ici (ce qui est une sorte de déception).

- (UIViewController*)terminalViewController:(UIViewController*)viewController
{
  if ([viewController isKindOfClass:[UITabBarController class]])
  {
    viewController = [(UITabBarController*)viewController selectedViewController];
    viewController = [self terminalViewController:viewController];
  }
  else if ([viewController isKindOfClass:[UINavigationController class]])
  {
    viewController = [[(UINavigationController*)viewController viewControllers] lastObject];
  }

  return viewController;
}

- (NSUInteger)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
  NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
  UIViewController* viewController = [self terminalViewController:window.rootViewController];

  if (viewController)
    orientations = [viewController supportedInterfaceOrientations];

  return orientations;
}

Un autre élément clé à noter est que vous devez remplacer les attributs supportedInterfaceOrientations dans vos sous-classes UIViewController, sinon ce sera la valeur que vous avez spécifiée dans votre Info.plist.

0
Ray Fix

Si vous utilisez UINavigationController, vous devez implémenter shouldAutorotate et supportedInterfaceOrientations dans la sous-classe de UINavigationController.

Ceux-ci peuvent être contrôlés par deux étapes, si shouldAutorotate renvoie YES puis effectif supportedInterfaceOrientations. C'est une très belle combinaison.

Cet exemple, mes vues les plus courantes sont Portrait sauf CoverFlowView et PreviewView . Le transfert CoverFlowView vers PreviewView, PreviewView veut suivre la rotation de CoverFlowCView.

@implementation MyNavigationController

-(BOOL)shouldAutorotate
{

if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(@"PreviewView")])

return NO;

else

return YES;

}



-(NSUInteger)supportedInterfaceOrientations

{

if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(@"CoverFlowView")])

return UIInterfaceOrientationMaskAllButUpsideDown;

else

return UIInterfaceOrientationMaskPortrait;

}

...

@end
0
Y.Muranaka

ma solution: sous-classe UINavigationController et la définir comme window.rootViewController

le contrôleur de vue de dessus de la hiérarchie prendra le contrôle de l'orientation, quelques exemples de code: sous-classe UINavigationController

0
Carina

Essayez d'ajouter la méthode shouldAutorotate

0
Kubba

J'ai la même situation que toi. Je sais que vous avez déjà accepté une réponse, mais je pensais en ajouter une de toute façon. C’est ainsi que je comprends la nouvelle version du système de rotation. Le contrôleur de vue racine est le seul contrôleur de vue jamais appelé. Je pense que le raisonnement est que, avec les contrôleurs de vue enfant, il n’est pas souvent logique de faire pivoter leurs vues car ils resteront dans le cadre du contrôleur de vue racine. 

Alors, qu'est-ce qui se passe. La première shouldAutorotate s'appelle sur le contrôleur de vue racine . Si NO est renvoyé, tout s'arrête. Si YES est renvoyé, la méthode supportedInterfaceOrientations est invoquée. Si l'orientation de l'interface est confirmée dans cette méthode et les orientations globales prises en charge par Info.plist ou par le délégué d'application, la vue pivote. Avant la rotation, la méthode shouldAutomaticallyForwardRotationMethods est interrogée. Si YES (valeur par défaut), tous les enfants recevront les méthodes will et didRotateTo... ainsi que le parent (et ils le transmettront à leurs enfants).

Ma solution (en attendant une solution plus éloquente) consiste à interroger le dernier contrôleur de vue enfant au cours de la méthode supportedInterfaceOrientations et à renvoyer sa valeur. Cela me permet de faire pivoter certaines zones tout en ne laissant que le portrait. Je me rends compte que c'est fragile, mais je ne vois pas d'autre moyen de ne pas compliquer les choses avec des appels d'événements, des rappels, etc. 

0
borrrden

Tout d'abord, pour que votre application fonctionne uniquement en mode, vous devez renvoyer UIInterfaceOrientationMaskLandscape. Si vous souhaitez ne garder que le mode portrait, vous faites les choses correctement.

Ajoutez simplement la clé UISupportedInterfaceOrientations dans Info.plist et attribuez les valeurs d’orientation de l’interface que votre application souhaite conserver.

En outre, vous devriez renvoyer false à partir de shouldAutoRotate au cas où vous souhaiteriez éviter totalement la rotation automatique. Mais je vous suggérerais de retourner true à partir d’ici et de spécifier les orientations correctes dans la méthode supportedInterfaceOrientations.

0
Varun Bhatia