web-dev-qa-db-ja.com

iOS 6でプログラムでデバイスの向きを変更する方法

iOS 5では、デバイスの向きを次のようにプログラムで変更できます。

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];

しかし、iOS 6setOrientationは非推奨ですが、iOS 6でデバイスの向きをプログラムで変更するにはどうすればよいですか?

45
uttam

以下は、ARCを使用してiOS7でテストした「5セント」です。

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

これは、performSelectorのように「リーク」警告を生成しません。

IAlertView-このコードでは、view(will/Did)の表示中にUIAlertViewを開くと、このビュー以外はすべて縦向きになっていることに気付くでしょう(Apple、本当に?)ビューの向きを変更しますが、UIAlertViewを開く前にわずかな遅延を設定すると、ビューの向きを変更する時間があります。

2014年9月12日からアプリの週をリリースします。成功または失敗した場合、投稿を更新します。

これは、デバイスの向きを変更する方法ではなく、役立つ可能性のある追加情報を提供します。

iOS 6 UIインターフェイスの向き-shouldAutorotateToInterfaceOrientation:動作していません

メソッドshouldAutorotateToInterfaceOrientation:はiOS 6ではサポートされていません。廃止されました。あなたが初心者で、ココアで仕事を始めたばかりで、なぜあなたのView ControllerがiOS 6で混乱し、iOS 5で完璧なのか疑問に思っている場合は、shouldAutorotateToInterfaceOrientation:はもうサポートされていません。 Xcode 4から4.3ではうまく動作するかもしれませんが、Xcode 4.5では動作しません。

Appleは、このことをよりクリーンな方法で実現する新しい方法を提供しています。代わりにsupportedInterfaceOrientationsを使用します。 View Controllerがサポートするすべてのインターフェイスの向き、インターフェイスの向きの値のマスクを返します。

UIInterfaceOrientationMask列挙:

これらの定数は、View Controllerのサポートされているインターフェイスの向きを指定するためのマスクビットです。

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;

shouldAutorotateToInterfaceOrientationの使用:method:

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

supportedInterfaceOrientationsメソッドの使用:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscapeRight;
}

これらはiOS6でのオリエンテーションに関してUIViewControllerに追加されたメソッドです

  1. IViewController preferredInterfaceOrientationForPresentation

  2. IViewController shouldAutorotate

  3. IViewController supportedInterfaceOrientations

iOS6の向きに関するメソッドをUIApplicationに追加

  1. IApplication supportedInterfaceOrientationsForWindow:

  2. IInterfaceOrientationMask

20
Bala

デバイスの向きを強制的に変更する最も簡単な方法は、新しいView Controllerを提示することです(presentViewController:animated:completion:を使用)、新しいView Controllerは特定の優先方向を指定します(メソッド-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation )。

予想どおり、新しいView Controllerが表示されると、向きは新しいView Controllerが優先する向きに変わります。したがって、最も簡単な実装(ベストプラクティス?)は、特定の方向に必要なすべての機能を別のView Controllerに埋め込み、必要に応じて表示することです。システムは、方向を変更します。

明らかに、これはすべてのユースケースに適しているわけではありませんが、幸いにも同じトリックを適用して、既存のView Controllerの向きをデバイスに強制的に変更できます。

トリックは、必要な特定の優先方向で新しいView Controllerを提示し、すぐに非表示にすることです。これにより、新しいView Controllerが表示されたときに向きが一時的に変更されます。最良の部分は、新しいView Controllerが閉じられると、元の(表示する)View ControllerのpreferredInterfaceOrientationForPresentationが再度クエリされることです。ここで、最終的な向きを指定できます。

ここで注目すべき重要なことの1つは、元のView Controllerで自動回転を一時的に無効にすることです(新しく表示されて終了したView Controllerから戻った場合)。さらに自動回転をトリガーしました。

次のコードは私のポイントを説明するものであり、この例では強制的に回転させてポートレートにし、他の方向にしたい場合はそれに応じて変更します。

Originalという名前の元のView Controllerと、ForcePortraitという名前の一時的なView Controllerがあるとします

@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.

これを試して:

#import <objc/message.h>

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

あなたが配置する必要があります
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
AppDelegate didFinishLaunchingWithOptionsメソッド内。

次に、アプリケーションのどこでも次の方法で現在の方向を取得できます。

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

そして、オリエンテーションをテストします:

UIInterfaceOrientationIsPortrait(orientation) 
UIInterfaceOrientationIsLandscape(orientation)

など

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

このコードはiOS 8以降用です

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

ランタイムライブラリの使用を避けたい場合は、Bissyの答えを少し修正します。

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

これを試してください...それは私のためにうまくいった...

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

Appleは、デバイスの方向を ios6 でプログラム的に変更することを非常に困難にしました(意図的にあなたに注意してください)。

私が知る限り、あなたが求めていることを達成する唯一の方法は、デバイスの向きの変化をシミュレートすることです。

setTransformを使用してUIViewを回転させ、独自のフレームを再適用すると、望ましい結果が得られます。

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

そして、デバイスの物理的な向きが変わると、変換を元に戻すことができます。

- (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

これはiOS7で機能し、自動回転をポートレートに強制します。

//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;
}

注:私はこのオプションをアプリに実装しましたが、おそらくApple(2012年10月に編集されたSergey K.のAustinのコメント6)によって拒否されます。

2
ppVen

@implementation UINavigationController(自動回転)

 -(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

これは、Xcode 6および5で機能します。

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