web-dev-qa-db-fra.com

Comment modifier l'orientation de l'appareil par programme dans iOS 6

Dans iOS 5 , nous pourrions modifier l’orientation de l’appareil par programme, comme suit:

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];

Mais dans iOS 6 setOrientation est obsolète, comment puis-je modifier l'orientation de l'appareil par programme dans iOS 6 ?

44
uttam

Voici mes "cinq centimes" testés sur iOS7 avec ARC

[[UIDevice currentDevice] setValue:
                      [NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
                            forKey:@"orientation"];

Cela ne génère pas d'avertissement de "fuite" comme le ferait PerformSelector.

UIAlertView - avec ce code, lorsque vous ouvrez UIAlertView pendant une vue (apparaissant/apparaissant), vous remarquerez que tout sauf cette vue est en portrait (Apple, vraiment?) Je n'ai pas réussi à forcer la vue à se réorienter mais vous avez constaté que si vous mettez un léger délai avant d’ouvrir UIAlertView, la vue a le temps de changer d’orientation.

Remarque Je publie ma semaine d'applications à partir du 12/09/2014 et je mettrai à jour le post s'il réussit ou échoue.

47

Cela ne vous indique pas comment modifier l'orientation du périphérique, mais une information supplémentaire susceptible de vous aider.

iOS 6 Orientation de l'interface utilisateur - shouldAutorotateToInterfaceOrientation: Ne fonctionne pas

La méthode shouldAutorotateToInterfaceOrientation}: N'EST PAS prise en charge par iOS 6. Son obsolète. Juste au cas où vous êtes un débutant qui commence à travailler dans le cacao et se demande pourquoi votre contrôleur de vue est gâché dans iOS 6 et parfait dans iOS 5, sachez simplement que shouldAutorotateToInterfaceOrientation: n'est plus supporté. Même si cela fonctionne bien avec Xcode 4 à 4.3, cela ne fonctionnera PAS sur Xcode 4.5. 

Apple fournit une nouvelle méthode pour résoudre ce problème, de manière beaucoup plus propre. Vous utilisez plutôt supportedInterfaceOrientations. Il renvoie toutes les orientations d'interface prises en charge par le contrôleur de vue, ainsi qu'un masque de valeurs d'orientation d'interface.

UIInterfaceOrientationMask Enum:

Ces constantes sont des bits de masque permettant de spécifier les orientations d’interface prises en charge par un contrôleur de vue.

typedef enum {
    UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
    UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
    UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
    UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
    UIInterfaceOrientationMaskLandscape =
        (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
    UIInterfaceOrientationMaskAll =
        (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft |
    UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
    UIInterfaceOrientationMaskAllButUpsideDown =
        (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft |
    UIInterfaceOrientationMaskLandscapeRight),
} UIInterfaceOrientationMask;

Utilisation de shouldAutorotateToInterfaceOrientation: method:

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return UIInterfaceOrientationIsLandscapeRight(toInterfaceOrientation);
}

Utilisation de la méthode supportedInterfaceOrientations:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscapeRight;
}

Ce sont les méthodes ajoutées à UIViewController concernant l'orientation dans iOS6}

  1. UIViewController preferredInterfaceOrientationForPresentation

  2. UIViewController devraitAutorotate

  3. UIViewController supportedInterfaceOrientations

Ajout de méthodes à UIApplication concernant l'orientation dans iOS6

  1. UIApplication supportedInterfaceOrientationsForWindow:

  2. UIInterfaceOrientationMask

20
Bala

J'ai découvert que le moyen le plus simple de forcer le périphérique à modifier l'orientation est de présenter un nouveau contrôleur de vue (à l'aide de presentViewController:animated:completion:), le nouveau contrôleur de vue spécifiant une orientation préférée particulière (en implémentant la méthode -(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation).

Lorsqu'un nouveau contrôleur de vue est présenté, comme prévu, l'orientation changera pour celle préférée par le nouveau contrôleur de vue. Ainsi, la mise en œuvre la plus simple (meilleure pratique?) Consistera à incorporer toutes les fonctionnalités dont vous avez besoin dans une orientation spécifique dans un contrôleur de vue séparé et à les présenter selon vos besoins. Le système se chargera de changer l'orientation pour vous.

Évidemment, cela pourrait ne pas convenir à tous les cas d'utilisation, mais heureusement, la même astuce est applicable pour forcer le périphérique à changer d'orientation pour le contrôleur de vue existant. 

L'astuce consiste à présenter un nouveau contrôleur de vue avec l'orientation préférée spécifique dont vous aviez besoin, puis à le masquer immédiatement. Cela entraînera une modification temporaire de l'orientation lorsque le nouveau contrôleur de vue est présenté. La meilleure partie est que, lorsque le nouveau contrôleur de vue est congédié, la variable preferredInterfaceOrientationForPresentation du contrôleur de vue d'origine (présentant) est interrogée à nouveau, vous pouvez spécifier l'orientation finale que vous souhaitez ici.

Une chose importante à regarder ici est de désactiver temporairement la rotation automatique dans le contrôleur de vue original (lorsque vous revenez du contrôleur de vue nouvellement présenté puis rejeté), afin que l'utilisateur ne fasse pas pivoter son téléphone dans la nouvelle orientation, déclenché une autre rotation automatique.

Le code suivant devrait illustrer mon propos, mon exemple force la rotation à portrait, changez simplement en conséquence si vous voulez une autre orientation. 

En supposant que vous ayez le contrôleur de vue d'origine nommé Original et un contrôleur de vue temporaire nommé ForcePortrait

@interface Original : UIViewController
{
    BOOL orientationToPortrait; //should set to NO by default
}
@end

@implementation Original
- (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation
{
    if(orientationToPortrait)
    {
        //when we manually changed, show in Portrait
        return UIInterfaceOrientationPortrait;
    }
    else
    {
        //before manual orientation change, we allow any orientation
        return self.interfaceOrientation;
    }
}

-(BOOL) shouldAutorotate
{
    //we should 'lock' the rotation once we manually change it
    return !orientationToPortrait;
}

-(void) changeOrientationToPortrait
{
    //Sample method to change the orientation
    //when called, will show (and hide) the temporary view
    //Original.preferredInterfaceOrientationForPresentation will be called again after this method

    //flag this to ensure that we tell system we prefer Portrait, whenever it asked again
    orientationToPortrait = YES;

    //presenting the following VC will cause the orientation to temporary change
    //when the new VC is dismissed, system will ask what is our (Original) orientation preference again
    ForcePortrait* forcePortrait = [[ForcePortrait alloc] init];
    [self presentViewController:forcePortrait animated:NO completion:^{
        [forcePortrait dismissViewControllerAnimated:NO completion:nil];
    }];
}


@end

@interface ForcePortrait : UIViewController
@end

@implementation ForcePortrait
- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}
@end
20
P.L.

Essaye ça:

#import <objc/message.h>

if(UIDeviceOrientationIsLandscape(self.interfaceOrientation)){
        if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
        {
            objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait );
        }
    }
10
Bissy

Vous devriez placer
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
dans votre méthode AppDelegate didFinishLaunchingWithOptions.

Ensuite, n'importe où dans votre application, vous pouvez obtenir l'orientation actuelle avec:

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

Et testez l'orientation avec:

UIInterfaceOrientationIsPortrait(orientation) 
UIInterfaceOrientationIsLandscape(orientation)

comme

if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
    // code for landscape orientation
     // OR
    [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
     //  OR
    [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];

}
else if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation))
{
    // code for Portrait orientation
    //  OR
   [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortraitUpsideDown];
    //  OR
   [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
}
5
user2289379

Ce code est pour iOS 8 ou version ultérieure

NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
4
Raul Quispe

Une petite modification à la réponse de Bissy, si vous voulez éviter d'utiliser Runtime Library:

if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]))
{
    if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
    {
        int orientationPortrait = UIInterfaceOrientationPortrait;
        NSMethodSignature *sig = [[UIDevice currentDevice] methodSignatureForSelector:@selector(setOrientation:)];
        NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig];
        [invo setTarget:[UIDevice currentDevice]];
        [invo setSelector:@selector(setOrientation:)];
        [invo setArgument:&orientationPortrait atIndex:2];
        [invo invoke];
    }
}
2
Perisheroy

Essayez ceci ... Cela a fonctionné pour moi ...

UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview]; [window addSubview:view];
2
Hiren Patel

Apple a rendu très difficile le changement de l'orientation de l'appareil par programme dans ios6 (vous le faites exprès).

Autant que je sache, le seul moyen d'accomplir ce que vous demandez est de simuler le changement d'orientation de l'appareil.

Utiliser setTransform pour faire pivoter la UIView et réappliquer son propre cadre donne les résultats souhaités.

[YourView setTransform:CGAffineTransformMakeRotation(1.57)];
[YourView setFrame:CGRectMake(0, 0, YourView.frame.size.width, YourView.frame.size.height)];

Et lorsque l'orientation physique du périphérique change, nous pouvons annuler la transformation.

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [YourView setTransform:CGAffineTransformMakeRotation(0)];
    [YourView setFrame:CGRectMake(0, 0, YourView.frame.size.width, YourView.frame.size.height)];
}
2
Aleksander Azizi

Cela fonctionne pour iOS7, force autorotate à portrait.

//In your viewController.m
#import <objc/message.h>

// for autorotate viewController to portraid
- (void)viewWillAppear:(BOOL)animated {
    UIInterfaceOrientation orientationStatusBar =[[UIApplication sharedApplication] statusBarOrientation];
    switch (orientationStatusBar) {
        case UIInterfaceOrientationPortrait:break;
        case UIInterfaceOrientationLandscapeLeft:
            objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait);
            break;
        case UIInterfaceOrientationLandscapeRight:
            objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait);
            break;
        default:
            break;
    }
}

// this permit autorotate
- (BOOL) shouldAutorotate
{
   // this lines permit rotate if viewController is not portrait
    UIInterfaceOrientation orientationStatusBar =[[UIApplication sharedApplication] statusBarOrientation];
    if (orientationStatusBar != UIInterfaceOrientationPortrait) {
        return YES;
    }
    //this line not permit rotate is the viewController is portrait
    return NO;
}

NOTE: J'ai implémenté cette option dans mon application, mais je serais probablement rejeté par Apple.

2
ppVen

@implementation UINavigationController (autorotation)

 -(NSUInteger)supportedInterfaceOrientations
 {
   //make the check for iphone/ipad here

    if(IPHONE)
    {
      return UIInterfaceOrientationMaskPortrait;
    } 
    else
    {
      return UIInterfaceOrientationMaskLandscape;
    }
 }

 - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
 {
    return UIInterfaceOrientationPortrait;
 }

 - (BOOL)shouldAutorotate
 {
    return NO;
 }
2
Shauket Sheikh
if (self.interfaceOrientation != UIInterfaceOrientationLandscapeRight) {
// http://stackoverflow.com/questions/181780/is-there-a-documented-way-to-set-the-iphone-orientation
// http://openradar.appspot.com/radar?id=697
// [[UIDevice currentDevice] setOrientation: UIInterfaceOrientationLandscapeRight]; // Using the following code to get around Apple's static analysis...
[[UIDevice currentDevice] performSelector:NSSelectorFromString(@"setOrientation:") withObject:(id)UIInterfaceOrientationLandscapeRight];
}
1
n00bProgrammer
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{
    // Return YES for supported orientations
   return NO;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
   return  interfaceOrientation == UIInterfaceOrientationPortrait
           || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown ;
}
0
ganesh

Cela fonctionne pour moi sur Xcode 6 & 5.

- (BOOL)shouldAutorotate {return YES;}
- (NSUInteger)supportedInterfaceOrientations {return (UIInterfaceOrientationMaskPortrait);}
0
SamSmart