57 votes

IOS 6 force l'orientation du périphérique en mode paysage

J'ai donné une app à dire 10 vue des contrôleurs. J'ai utiliser la manette de navigation pour charger/décharger.

Tous, sauf un, sont en mode portrait. Supposons que le 7e VC est dans paysage. J'ai besoin d'elle pour être présenté dans le paysage quand il est chargé.

S'il vous plaît suggérer un moyen pour forcer l'orientation de passer de portrait à paysage dans IOS 6 (et il sera bon de travailler dans IOS 5).

Voici comment je le faisais AVANT IOS 6:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    UIViewController *c = [[[UIViewController alloc]init] autorelease];
    [self presentModalViewController:c animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

La présentation et à la révocation d'un modal VC était de forcer l'application à l'examen de son orientation, afin shouldAutorotateToInterfaceOrientation a été appelé.

Ce que j'ai essayé, à IOS 6:

- (BOOL)shouldAutorotate{
    return YES;
}
-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
    return UIInterfaceOrientationLandscapeLeft;
}

Sur la charge, le contrôleur est apprécié des voyageurs séjournant dans le portrait. Après la rotation de l'appareil, l'orientation des changements dans la juste ok. Mais j'ai besoin de faire le contrôleur pour faire pivoter automatiquement en mode paysage sur la charge, ainsi l'utilisateur devra faire pivoter l'appareil pour voir correctement les données.

Un autre problème: après la rotation de l'appareil vers l'arrière pour le portrait, l'orientation va à portrait, bien que j'ai spécifié dans supportedInterfaceOrientations seulement UIInterfaceOrientationMaskLandscape. Pourquoi ça arrive?

Aussi, AUCUN de plus de 3 méthodes sont appelé.

Certaines données utiles:

  1. Dans mon fichier plist j'ai spécifié 3 orientations - tous, mais à l'envers.
  2. Le projet a été lancé dans Xcode 4.3 d'IOS 5. Toutes les classes y compris xibs ont été créés avant Xcode 4.5 IOS 6, maintenant j'utilise la dernière version.
  3. Dans un fichier plist la barre d'état est définie à visible.
  4. Dans le fichier xib (celui que je veux être en mode paysage) la barre d'état est "None", l'orientation est paysage.

Toute aide est appréciée. Merci.

43voto

Sava Mazăre Points 1904

Ok, les gars, je vais poster ma solution.

Ce que j'ai:

  1. Une vue en fonction de l'application, avec plusieurs contrôleurs de vue. (Il était de navigation, mais j'ai dû rendre la vue, en raison de questions liées à l'orientation).
  2. Tous les contrôleurs de vue portrait, à l'exception d'un landscapeLeft.

Tâches:

  1. Un de mes contrôleurs de vue doit automatiquement pivoter en mode paysage, peu importe la façon dont l'utilisateur tient l'appareil. Tous les autres contrôleurs doit être le portrait, et après avoir quitté le paysage contrôleur, l'application doit force de faire pivoter en mode portrait, peu importe, encore une fois, la façon dont l'utilisateur tient l'appareil.
  2. Cela doit fonctionner que sur IOS 6.x comme sur IOS 5.x

Allez!

(Mise à jour Retiré les macros suggéré par @Ivan Vučica)

Dans tous les votre PORTRAIT contrôleurs de remplacer l'autorotation méthodes comme ceci:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
-(BOOL)shouldAutorotate {
    return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

Vous pouvez voir les 2 approches: l'une pour IOS 5 et l'autre Pour IOS 6.

La même chose pour votre PAYSAGE-vue-contrôleur, avec quelques ajouts et modifications:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
    [image_signature setImage:[self resizeImage:image_signature.image]];
    return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
-(BOOL)shouldAutorotate {
    return YES;
}
- (NSUInteger)supportedInterfaceOrientations {
    [image_signature setImage:[self resizeImage:image_signature.image]];
    return UIInterfaceOrientationMaskLandscapeLeft;
}

ATTENTION: à force de autorotation dans IOS 5 , vous devez ajouter ceci:

- (void)viewDidLoad{
    [super viewDidLoad];
    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
        [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeLeft animated:NO];    
}

Analogiquement, après que vous quittez le PAYSAGE contrôleur, quel que soit le contrôleur de vous charger, vous devriez force de rotation automatique pour IOS 5, mais maintenant vous allez utiliser UIDeviceOrientationPortrait,, vous accédez à un PORTRAIT de contrôleur:

- (void)viewDidLoad{
        [super viewDidLoad];
        if ([[[UIDevice currentDevice] systemVersion] floatValue] < 6.0)
            [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationPortrait animated:NO];    
    }

Maintenant, la dernière chose (et c'est un peu bizarre) - vous devez changer la façon dont vous passez à partir d'un contrôleur à l'autre, selon le IOS:

Faire une classe NSObject "Schalter" ("Switch" de l'allemand).

Dans Schalter.h-dire:

#import <Foundation/Foundation.h>

@interface Schalter : NSObject
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease;
@end

Dans Schalter.m-dire:

#import "Schalter.h"
#import "AppDelegate.h"

@implementation Schalter
+ (void)loadController:(UIViewController*)VControllerToLoad andRelease:(UIViewController*)VControllerToRelease{

    //adjust the frame of the new controller
    CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];
    CGRect windowFrame = [[UIScreen mainScreen] bounds];
    CGRect firstViewFrame = CGRectMake(statusBarFrame.origin.x, statusBarFrame.size.height, windowFrame.size.width, windowFrame.size.height - statusBarFrame.size.height);
    VControllerToLoad.view.frame = firstViewFrame;

    //check version and go
    if (IOS_OLDER_THAN_6)
        [((AppDelegate*)[UIApplication sharedApplication].delegate).window addSubview:VControllerToLoad.view];
    else
        [((AppDelegate*)[UIApplication sharedApplication].delegate).window setRootViewController:VControllerToLoad];

    //kill the previous view controller
    [VControllerToRelease.view removeFromSuperview];
}
@end

MAINTENANT, c'est la façon dont vous utilisez Schalter ( en supposant que vous aller de l'Entrepôt contrôleur de contrôleur des Produits ) :

#import "Warehouse.h"
#import "Products.h"

@implementation Warehouse
Products *instance_to_products;

- (void)goToProducts{
    instance_to_products = [[Products alloc] init];
    [Schalter loadController:instance_to_products andRelease:self];
}

bla-bla-bla your methods

@end

Bien sûr, vous devez libérer instance_to_products objet:

- (void)dealloc{
     [instance_to_products release];
     [super dealloc];
}

Eh bien, c'est ça. N'hésitez pas à downvote, je n'ai pas de soins. C'est pour ceux qui sont à la recherche de solutions, pas pour la réputation. Cheers! Sava Mazare.

34voto

Chunkylover53 Points 355

Cela devrait fonctionner, il est similaire à la version antérieure à iOS 6, mais avec un UINavigationController :

 UIViewController *portraitViewController = [[UIViewController alloc] init];
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController:portraitViewController];
[self.navigationController presentModalViewController:nc animated:NO];
[self.navigationController dismissModalViewControllerAnimated:NO];
 

J'appelle cela avant de pousser le prochain UIViewController . Cela forcera les prochains UIViewController poussés à être affichés en mode Portrait, même si les UIViewController actuels sont en Paysage (cela devrait également fonctionner pour Portrait à Paysage). Fonctionne sur iOS 4 + 5 + 6 pour moi.

14voto

Skodik.o Points 217

Je pense que la meilleure solution est de s'en tenir à l'officiel d'apple de la documentation. Ainsi, selon que j'utilise une des méthodes suivantes et tout fonctionne très bien sur iOS 5 et 6. Dans mon CR je remplace méthodes suivantes:

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

Méthodes pour iOS 6, la première méthode retourne pris en charge l'orientation de masque (comme leur nom l'indiquent)

-(NSUInteger)supportedInterfaceOrientations{

    return UIInterfaceOrientationMaskPortrait;
}

deuxième thats dit votre VC qui est préféré interface d'orientation lors de la VC va être affiché.

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}

Il suffit de changer de Portrait pour l'orientation que vous voulez ;) Cette solution est de travailler en douceur, je n'aime pas l'idée de la création de macros et d'autres choses, qui tourne autour de cette solution simple. Espérons que cela aide...

7voto

Vlad Cioaba Points 79

J'ai eu le même problème, 27 vues dans mon application à partir de laquelle 26 en mode portrait et un seul dans toutes les orientations ( une visionneuse d'image :) ). L'ajout de la macro sur chaque classe et de remplacer la navigation n'était pas une solution que j'ai été à l'aise avec...

Donc, je voulais garder la UINavigationController mécanique dans mon application et de ne pas le remplacer par un autre code.

Quoi faire:

@1 le délégué d'application de la méthode didFinishLaunchingWithOptions

if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0)
{
    // how the view was configured before IOS6
    [self.window addSubview: navigationController.view];
    [self.window makeKeyAndVisible];
}
else
{
    // this is the code that will start the interface to rotate once again
    [self.window setRootViewController: self.navigationController];
}

@2 Parce que le navigationController sera juste responde avec OUI pour l'autorotation, nous devons ajouter quelques limitations: Étendre la UINavicationController -> YourNavigationController et lien dans Interface Builder.

@3 Remplacer "un de nouvelles méthodes" de la manette de navigation.

Étant donné que cette classe est de coutume que pour cette application, il peut prendre la responsabilité pour les contrôleurs et de répondre à leur place.

-(BOOL)shouldAutorotate {

    if ([self.viewControllers firstObject] == YourObject)
    {
         return YES;
    }
    return NO;
}
- (NSUInteger)supportedInterfaceOrientations {
     if ([self.viewControllers firstObject] == YourObject)
    {
         return UIINterfaceOrientationMaskLandscape;
    }
    return UIInterfaceOrientationMaskPortrait;
}

J'espère que cela va vous aider,

3voto

sjwarner Points 3137

À partir des notes de version iOS 6 :

À présent, les conteneurs iOS (tels que UINavigationController) ne consultent pas leurs enfants pour déterminer s’ils doivent effectuer une auto-rotation.

Votre rootViewController passent le shouldAutoRotate un message sur le ViewController hiérarchie à votre CV?

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