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.
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
.
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
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];
}
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.
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;
}
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;
}
Fondamentalement, comme quelqu'un l'a dit ci-dessus, mais plus en détail:
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
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.
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
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.
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
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
Essayez d'ajouter la méthode shouldAutorotate
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.
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
.