iOS 8でビューコントローラーの向きを強制する方法


149

iOS 8より前は、supportedInterfaceOrientationsおよびshouldAutoRotateデリゲートメソッドと組み合わせて以下のコードを使用して、アプリの向きを特定の向きに強制しました。以下のコードスニペットを使用して、プログラムでアプリを目的の向きに回転させました。まず、ステータスバーの向きを変更します。そして、モーダルビューを表示してすぐに閉じると、ビューが目的の方向に回転します。

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
UIViewController *c = [[UIViewController alloc]init];
[self presentViewController:vc animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];

しかし、これはiOS 8では失敗しています。また、スタックオーバーフローでいくつかの回答を見てきましたが、iOS 8以降はこのアプローチを常に避けるべきであると人々から提案されました。

具体的には、私のアプリケーションはユニバーサルタイプのアプリケーションです。合計3つのコントローラーがあります。

  1. First Viewコントローラ -iPadではすべての方向をサポートし、iPhoneではポートレート(ホームボタンを押した状態)のみをサポートする必要があります。

  2. セカンドビューコントローラー -すべての状況でランドスケープのみをサポートします

  3. サードビューコントローラー -すべての状況でランドスケープのみをサポートする必要があります

ページナビゲーションにはナビゲーションコントローラを使用しています。最初のビューコントローラーから、ボタンクリックアクションで、2番目のアクションをスタックにプッシュします。そのため、デバイスの向きに関係なく、2番目のビューコントローラーが到着すると、アプリは横向きにのみロックする必要があります。

以下は、2番目と3番目のビューコントローラーのmy メソッドshouldAutorotatesupportedInterfaceOrientationsメソッドです。

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscapeRight;
}

-(BOOL)shouldAutorotate {
    return NO;
}

これの解決策、またはiOS 8の特定の方向でビューコントローラをロックするより良い方法はありますか?助けてください!!


提示された VCで言及したメソッドの実装は、通常は機能するはずです(少なくとも、これはiOS 8での私の経験です)。おそらくあなたの特定の設定が問題を引き起こしていますか?
Vladimir Gritsenko 2014年

質問をもう少し明確にできるかもしれません。質問を少し編集します。
Rashmi Ranjan mallick 2014年

@VladimirGritsenko:今チェックしてください。編集しました。
Rashmi Ranjan mallick 2014年

問題のコードは、ナビゲーションコントローラーのスタックではなく、モーダルプレゼンテーションを使用しているため、正確に何をしているのかはまだ明確ではありません。私たちのコードでは、shouldAutoRotateからYESを返し、提示された VCのsupportedInterfaceOrientationsから目的の方向を返すと、そのVCが適切に方向付けられると言います。
Vladimir Gritsenko 2014年

まあ、それは実際には失敗ではありません、それは概念の大きな変化です。それが良い変化かどうかはまったく別の話題です。
Kegluneq 2014年

回答:


315

iOS 7〜10の場合:

Objective-C:

[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeLeft) forKey:@"orientation"];
[UINavigationController attemptRotationToDeviceOrientation];

スウィフト3:

let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()

- viewDidAppear:表示されたビューコントローラで呼び出すだけです。


61
これはプライベートAPIではありません。これはAPIの安全でない使用です。あなたはプライベートメソッドを使用していませんが、「内部のもの」を使用しています。Appleが "orientation"の値を変更すると、失敗します。さらに悪いことに、Appleが "orientation"値の意味を変更した場合、値をハード設定して何を変更しているかがわかりません。
sonxurxo 2014

4
アニメーションを無効にするには、関連[UIView setAnimationsEnabled:NO];viewWillAppear[UIView setAnimationsEnabled:YES];に 入れ てくださいviewDidAppearstackoverflow.com/a/6292506/88597
ohho

3
素敵なハックですが、その問題は、新しい方向の値(ため息)を設定した後、didRotateFromInterfaceOrientationを起動しないことです
loretoparisi

2
iOS 9.2では、これは方向を変えるだけでロックはしません。
Mark13426 2015

2
誰もがこの振る舞いいいの時間の90%を有し、かつ、時間の残りの10%にバグが多いために、オリエンテーションキーを設定した後、これを呼び出す:[UINavigationController attemptRotationToDeviceOrientation];
アルバート・レンショウ

93

UINavigationControllerまたはの内部にいる場合、向きの回転は少し複雑になりますUITabBarController。問題は、ビューコントローラーがこれらのコントローラーの1つに埋め込まれている場合、ナビゲーションまたはタブバーコントローラーが優先され、自動回転とサポートされている方向の決定を行うことです。

UINavigationControllerとUITabBarControllerで次の2つの拡張機能を使用して、これらのコントローラーの1つに埋め込まれているビューコントローラーが決定を行えるようにします。

View Controllerにパワーを与える!

Swift 2.3

extension UINavigationController {
    public override func supportedInterfaceOrientations() -> Int {
        return visibleViewController.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        return visibleViewController.shouldAutorotate()
    }
}

extension UITabBarController {
    public override func supportedInterfaceOrientations() -> Int {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations()
        }
        return super.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate()
        }
        return super.shouldAutorotate()
    }
}

スウィフト3

extension UINavigationController {
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return visibleViewController?.supportedInterfaceOrientations ?? super.supportedInterfaceOrientations
    }

    open override var shouldAutorotate: Bool {
        return visibleViewController?.shouldAutorotate ?? super.shouldAutorotate
    }
}

extension UITabBarController {
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations
        }
        return super.supportedInterfaceOrientations
    }

    open override var shouldAutorotate: Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate
        }
        return super.shouldAutorotate
    }
}

これで、supportedInterfaceOrientationsメソッドをオーバーライドするかshouldAutoRotate、ロックダウンするビューコントローラーでオーバーライドできます。それ以外の場合は、アプリのplistで指定されているデフォルトの向きの動作を継承する他のビューコントローラーでオーバーライドを省略できます。

ローテーションを無効にする

class ViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }
}

特定の方向にロック

class ViewController: UIViewController {
    override func supportedInterfaceOrientations() -> Int {
        return Int(UIInterfaceOrientationMask.Landscape.rawValue)
    }
}

理論的には、これはすべての複雑なView Controller階層で機能するはずですが、UITabBarControllerの問題に気づきました。何らかの理由で、デフォルトの向きの値を使用したいと考えています。一部の問題を回避する方法について知りたい場合は、次のブログ投稿を参照してください。

ロック画面の回転


1
これは非常に古い投稿であることは知っていますが、拡張コードをどこに配置しますか?
dwinnbrown 2015

7
Swiftのダウンマーキングは、Objective-Cの質問にのみ答えます。
チャーリースコットスキナー2015

17
これは、SwiftとObjCに適したソリューションです。人々がなぜ投票しないのか理解していない。アイデアを得て、コードを書くのは簡単です。なぜ文句を言う?
Zhao

2
@Krodak、拡張機能で「-> Int」を「-> UIInterfaceOrientationMask」に変更してみてください。私のためにトリックをしました。
the_pantless_coder

2
アイデアとコードは完璧ですが、大好きですが、UINavigationControllerを使用していて、横向きに表示されているUIViewControllerから縦向きに表示する必要があるUIViewControllerに戻ると問題が発生します。何か案は?
危機グリーガ2016年

24

これは私のために働いたものです:

https://developer.apple.com/library//ios/documentation/UIKit/Reference/UIViewController_Class/index.html#//apple_ref/occ/clm/UIViewController/attemptRotationToDeviceOrientation

viewDidAppear:メソッドで呼び出します。

- (void) viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [UIViewController attemptRotationToDeviceOrientation];
}

3
非常に便利な、デバイスがすでに回転させて、あなたはあなたのビューコントローラを回転させる必要がある場合
avdyushin

2
すばらしい答えです。受け入れられた回答と組み合わせて使用​​すると、SwiftとiOS 9以降で毎回うまく機能します。
AndyDunn

1
質問の答えではないと思いますが、本当に助かりました。
Abdurrahman Mubeen Ali 2016

21

表示されたビューコントローラーの場合、オーバーライドできることがわかりました preferredInterfaceOrientationForPresentation

迅速:

override func supportedInterfaceOrientations() -> Int {
  return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
  return UIInterfaceOrientation.LandscapeLeft
}

override func shouldAutorotate() -> Bool {
  return false
}

4
受け入れられた答えは単に横向きへの向きの変化を引き起こすようです。あなたがここに示されてきたことにする方法である強制するビューコントローラを唯一の風景の中にあること、そして(私が必要正確に何である)提示ビューコントローラには影響を与えません。ありがとう。
Clifton Labrum、2015年

1
@CliftonLabrum 風景だけを強制するために他に何かしましたか?同じコードを使用しても、ビューコントローラーは別の方向に回転できます。
Crashalot、2015

後で気づきました-あなたは正しいです。まだ修正方法が見つかりません。
Clifton Labrum、2015

1
これでうまくいきました。このコードを使用して、単一のビューコントローラーを縦向きモードに保つことができました(横向きを縦向きに置き換える)。+1
Mark Ba​​rrasso、2015

はい!これは、Xcode 7.3とSwift 2.2でも機能しました。ただし、AppDelegateでsupportedInterfaceOrientationsForWindowのfuncアプリケーションを定義する必要があります。
charles.cc.hsu

15

この方法は私にとってSwift 2 iOS 8.xで機能します:

PS(このメソッドは、すべてのviewControllerでshouldautorotateのような方向関数をオーバーライドする必要はなく、AppDelegateで1つのメソッドのみ)

プロジェクトの一般情報の「フルスクリーンが必要」を確認してください。 ここに画像の説明を入力してください

したがって、AppDelegate.swiftで変数を作成します。

var enableAllOrientation = false

だから、このfuncも入れてください:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
        if (enableAllOrientation == true){
            return UIInterfaceOrientationMask.All
        }
        return UIInterfaceOrientationMask.Portrait
}

したがって、プロジェクトのすべてのクラスで、この変数をviewWillAppearに設定できます。

override func viewWillAppear(animated: Bool)
{
        super.viewWillAppear(animated)
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        appDelegate.enableAllOrientation = true
}

デバイスタイプに基づいて選択する必要がある場合は、次のようにできます。

override func viewWillAppear(animated: Bool)
    {
        super.viewWillAppear(animated)
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        switch UIDevice.currentDevice().userInterfaceIdiom {
        case .Phone:
        // It's an iPhone
           print(" - Only portrait mode to iPhone")
           appDelegate.enableAllOrientation = false
        case .Pad:
        // It's an iPad
           print(" - All orientation mode enabled on iPad")
           appDelegate.enableAllOrientation = true
        case .Unspecified:
        // Uh, oh! What could it be?
           appDelegate.enableAllOrientation = false
        }
    }

とても良い説明
Oza

11

まず第一に、これは悪い考えです、一般的に、あなたのアプリのアーキテクチャで何かがおかしいのですがsh..t happens、もしそうなら、あなたは以下のようなものを作ることを試みることができます:

final class OrientationController {

    static private (set) var allowedOrientation:UIInterfaceOrientationMask = [.all]

    // MARK: - Public

    class func lockOrientation(_ orientationIdiom: UIInterfaceOrientationMask) {
        OrientationController.allowedOrientation = [orientationIdiom]
    }

    class func forceLockOrientation(_ orientation: UIInterfaceOrientation) {
        var mask:UIInterfaceOrientationMask = []
        switch orientation {
            case .unknown:
                mask = [.all]
            case .portrait:
                mask = [.portrait]
            case .portraitUpsideDown:
                mask = [.portraitUpsideDown]
            case .landscapeLeft:
                mask = [.landscapeLeft]
            case .landscapeRight:
                mask = [.landscapeRight]
        }

        OrientationController.lockOrientation(mask)

        UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
    }
}

よりも AppDelegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // do stuff
    OrientationController.lockOrientation(.portrait)
    return true
}

// MARK: - Orientation

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return OrientationController.allowedOrientation
}

そして、向きを変えたいときはいつでも:

OrientationController.forceLockOrientation(.landscapeRight)

注:場合によっては、デバイスがそのような呼び出しから更新されない可能性があるため、次のようにする必要があります

OrientationController.forceLockOrientation(.portrait)
OrientationController.forceLockOrientation(.landscapeRight)

それで全部です


9

これはiOS 6以降で機能するはずですが、私はiOS 8でのみテストしました。サブクラス化UINavigationControllerし、次のメソッドをオーバーライドします。

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationLandscapeRight;
}

- (BOOL)shouldAutorotate {
    return NO;
}

または、表示されているView Controllerに尋ねます

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return self.visibleViewController.preferredInterfaceOrientationForPresentation;
}

- (BOOL)shouldAutorotate {
    return self.visibleViewController.shouldAutorotate;
}

そこでメソッドを実装します。


iOS 10.0を実行しているXcode 8.2.1のアプリでこれをテストしたところ、動作しました。私のゲームメニューは最初の画面で、回転しません。他のすべてのビューは回転します。パーフェクト!1つ上げました。Mojo66が提供する「preferredInterfaceOrientationForPresentation」関数だけが必要でした。
フィリップボルヘス2017年

9

これは、以下を使用してアニメーションを無効にする方法に関する、シドシャーの回答のコメントへのフィードバックです。

[UIView setAnimationsEnabled:enabled];

コード:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:NO];
    [UIView setAnimationsEnabled:NO];

    // Stackoverflow #26357162 to force orientation
    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:NO];
    [UIView setAnimationsEnabled:YES];
}

これをポートレートにどのように使用できますか?
Muju、2016年

6

navigationViewControllerを使用している場合は、独自のスーパークラスを作成してオーバーライドする必要があります。

- (BOOL)shouldAutorotate {
  id currentViewController = self.topViewController;

  if ([currentViewController isKindOfClass:[SecondViewController class]])
    return NO;

  return YES;
}

これは、中回転を無効にしますSecondViewControllerが、あなたはあなたのプッシュする場合SecondViewControllerをお使いのデバイスが縦向きにあるとき、あなたのSecondViewControllerは、ポートレートモードで表示されます。

ストーリーボードを使用していると仮定します。手動のセグエ(方法)を作成し、「onClick」メソッドで作成する必要があります。

- (IBAction)onPlayButtonClicked:(UIBarButtonItem *)sender {
  NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
  [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
  [self performSegueWithIdentifier:@"PushPlayerViewController" sender:self];
}

これにより、スーパークラスが自動回転機能を無効にする前に、横向きになります。


6

Xcode 8のメソッドのプロパティに変換され、そうでは、次の作品Swift

override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.portrait
}

override public var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return UIInterfaceOrientation.portrait
}

override public var shouldAutorotate: Bool {
    return true
}

これは向きをロックしますか?
bnussey

1
@bnussey portraitiPadの向きに関係なく、自動回転を防ぎ、常にモードにしたかったので、shouldAutorotatetrueを返すことでそれを達成しました。
Ali Momen Sani

4

私は多くの解決策を試しましたが、うまくいったものは次のとおりです:

info.plistiOS 8および9で編集する必要はありません。

- (BOOL) shouldAutorotate {
    return NO;
}   

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return (UIInterfaceOrientationPortrait | UIInterfaceOrientationPortraitUpsideDown);
}

Appleドキュメントから可能な方向

UIInterfaceOrientationUnknown

デバイスの向きを特定できません。

UIInterfaceOrientationPortrait

デバイスは縦長モードであり、デバイスを直立させ、ホームボタンを下に置きます。

UIInterfaceOrientationPortraitUpsideDown

デバイスは縦向きモードですが、デバイスが直立しており、ホームボタンが上部にあります。

UIInterfaceOrientationLandscapeLeft

デバイスは横長モードであり、デバイスは直立して、ホームボタンは左側にあります。

UIInterfaceOrientationLandscapeRight

デバイスは横長モードであり、デバイスは直立しており、ホームボタンは右側にあります。


3

SidsとKoreysの回答を組み合わせるとうまくいきました。

ナビゲーションコントローラーの拡張:

extension UINavigationController {
    public override func shouldAutorotate() -> Bool {
        return visibleViewController.shouldAutorotate()
    }
}

次に、単一のビューの回転を無効にします

class ViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }
}

そして、セグの前に適切な方向に回転します

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if (segue.identifier == "SomeSegue")
    {
        let value = UIInterfaceOrientation.Portrait.rawValue;
        UIDevice.currentDevice().setValue(value, forKey: "orientation")
    }
}

これが、表示されるビューコントローラーが、通常のように縦向きに回転する前に1秒間横向きになる問題に役立つかどうかを知っていますか?質問はここにある:stackoverflow.com/questions/30693964/...
dwinnbrown

3

上記のトップソリューション:

let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")

表示されたビューコントローラーのviewDidAppearで呼び出したときに機能しませんでした。ただし、表示しているビューコントローラーのpreparForSegueで呼び出したときに機能しました。

(申し訳ありませんが、そのソリューションについてコメントするには評判が足りないため、このように追加する必要がありました)


私はこれを機能させましたが、横向きのビューコントローラーから縦向きのビューコントローラーに移行すると、縦向きで表示されるはずのビューコントローラーが、自然に回転する前に横向きで簡単に表示されます。誰が助ける方法を知っているならば、私の質問はここにある:stackoverflow.com/questions/30693964/...
dwinnbrown

@dwinnbrown at viewDidAppearビューコントローラーは既に表示されています。多分代わりにviewDidLoadから試してください?
Crashalot、2015

@Crashalot私はこれを修正しました。私が正しいとマークした答えを見てください。
dwinnbrown 2015

@dwinnbrownあなたの質問へのリンクは死んでいます。更新?ありがとう!
Crashalot、2015

@Crashalotコミュニティが削除しましたが、元に戻すことを投票しました。すぐにお知らせします
dwinnbrown 2015

3

[iOS9 +]上記のいずれの解決策も機能せず、誰かがここまで下にドラッグした場合、ビューを提示してセグエによって方向を変更したい場合は、これを確認する必要があります。

セグエのプレゼンテーションタイプを確認します。鉱山は「現在の状況を超えて」いた。フルスクリーンに変更するとうまくいきました。

@GabLeRouxのおかげで、私はこの解決策を見つけました。

  • この変更は、上記のソリューションと組み合わせた場合にのみ機能します。

2

私の要件は

  1. ポートレートモードですべてのビューをロックする
  2. AVPlayerViewControllerビデオの再生に使用

ビデオの再生時に横向きの場合、画面を横向きに右に回転させ、左向きに回転させます。縦長の場合は、縦長モードでのみビューをロックします。

まず、定義supportedInterfaceOrientationsForWindowAppDelegate.swift

var portrait = true
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if portrait {
        return .Portrait
    } else {
        return .Landscape
    }
}

次に、メインのビューコントローラーで、次の関数を定義します。

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    print("\(#function)")
    return .Portrait
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    return .Portrait
}

override func shouldAutorotate() -> Bool {
    return false
}

次に、サブクラス化する必要があります AVPlayerViewController

class MyPlayerViewController: AVPlayerViewController {

    var size: CGSize?

    var supportedOrientationMask: UIInterfaceOrientationMask?
    var preferredOrientation: UIInterfaceOrientation?

    override func viewDidLoad() {
        super.viewDidLoad()

        if let size = size {
            if size.width > size.height {
                self.supportedOrientationMask =[.LandscapeLeft,.LandscapeRight]
                self.preferredOrientation =.LandscapeRight
            } else {
                self.supportedOrientationMask =.Portrait
                self.preferredOrientation =.Portrait
            }
        }
    }

これら3つの関数をオーバーライドします MyPlayerViewController.swift

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return self.supportedOrientationMask!
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    return self.preferredOrientation!
}

ユーザーはデバイスの横向きまたは右向きに回転する可能性があるため、自動回転をtrueに設定する必要があります

override func shouldAutorotate() -> Bool {
    return true
}

最後に、MyPlayerViewControllerビューコントローラーでインスタンスを作成し、プロパティサイズの値を設定します。

let playerViewController = MyPlayerViewController()

// Get the thumbnail  
let thumbnail = MyAlbumFileManager.sharedManager().getThumbnailFromMyVideoMedia(......)

let size = thumbnail?.size
playerViewController.size = size

適切なvideoUrlでプレーヤーを開始し、次にプレーヤーをに割り当てますplayerViewController。幸せなコーディング!



1

このタスクを達成するための最良の方法についてはまだ議論があるようですので、私は(実際の)アプローチを共有したいと思いました。UIViewController実装に次のコードを追加します。

- (void) viewWillAppear:(BOOL)animated
{
    [UIViewController attemptRotationToDeviceOrientation];
}

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

-(BOOL)shouldAutorotate
{
    return NO;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscapeLeft;
}

この例では、プロジェクト設定で(またはで直接info.plist)、許可されているデバイスの向きを「Landscape Left」に設定する必要もあります。以外の何かが必要な場合は、強制したい特定の方向を変更するだけですLandscapeLeft.

私にとって重要だったのは、attemptRotationToDeviceOrientation電話をかけてきたviewWillAppearことです。それがないと、デバイスを物理的に回転させないと、ビューが適切に回転しません。


非推奨のメソッド。
Saqib Omer、

1

コレイヒントンの答えによると

Swift 2.2:

extension UINavigationController {
    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return visibleViewController!.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        return visibleViewController!.shouldAutorotate()
    }
}


extension UITabBarController {
    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations()
        }
        return super.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate()
        }
        return super.shouldAutorotate()
    }
}

ローテーションを無効にする

override func shouldAutorotate() -> Bool {
    return false
}

特定の方向にロック

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.Portrait
}

1

ここでいくつかの解決策を試しましたが、理解する必要がある重要なことは、回転するかどうかを決定するのはルートビューコントローラーであることです。

私は、次のように作成Objective-Cのプロジェクトgithub.com/GabLeRoux/RotationLockInTabbedViewChildを Aの作業例でTabbedViewController1つのビューが回転し許可され、他の子ビューが肖像画にロックされています。

完璧ではありませんが、機能します。同じアイデアは、などの他の種類のルートビューでも機能しNavigationViewControllerます。:)

子ビューは親の向きをロックします


0

@ sid-shaによって示されたソリューションによると、すべてをviewDidAppear:メソッドに配置する必要がありますdidRotateFromInterfaceOrientation:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
        interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        NSNumber *value = [NSNumber numberWithInt:interfaceOrientation];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    }
}

0

私の解決策

AppDelegate

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if let topController = UIViewController.topMostViewController() {
        if topController is XXViewController {
            return [.Portrait, .LandscapeLeft]
        }
    }
    return [.Portrait]
}

XXViewController 横長モードをサポートするViewControllerです。

次に、Sunny ShahのソリューションXXViewController、どのiOSバージョンでも動作します。

let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")

これは、最上位のViewControllerを見つけるためのユーティリティ関数です。

extension UIViewController {

    /// Returns the current application's top most view controller.
    public class func topMostViewController() -> UIViewController? {
        let rootViewController = UIApplication.sharedApplication().windows.first?.rootViewController
        return self.topMostViewControllerOfViewController(rootViewController)
    }



    /// Returns the top most view controller from given view controller's stack.
    class func topMostViewControllerOfViewController(viewController: UIViewController?) -> UIViewController? {
        // UITabBarController
        if let tabBarController = viewController as? UITabBarController,
           let selectedViewController = tabBarController.selectedViewController {
            return self.topMostViewControllerOfViewController(selectedViewController)
        }

        // UINavigationController
        if let navigationController = viewController as? UINavigationController,
           let visibleViewController = navigationController.visibleViewController {
            return self.topMostViewControllerOfViewController(visibleViewController)
        }

        // presented view controller
        if let presentedViewController = viewController?.presentedViewController {
            return self.topMostViewControllerOfViewController(presentedViewController)
        }

        // child view controller
        for subview in viewController?.view?.subviews ?? [] {
            if let childViewController = subview.nextResponder() as? UIViewController {
                return self.topMostViewControllerOfViewController(childViewController)
            }
        }

        return viewController
    }

}

0

これを使用して、IOS 9でテストされたビューコントローラの向きをロックします。

//向きを横向きに固定します

-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscapeRight;
}

-(NSUInteger)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController {
    return UIInterfaceOrientationMaskLandscapeRight;
}

0

私は同じ問題を抱えており、そのために多くの時間を浪費しています。だから今私は私の解決策を持っています。マイアプリの設定はちょうどサポートの肖像画であるonly.However、私のアプリへの一部の画面には、それを修正して、変数持つonly.I風景持っている必要がisShouldRotateをAppDelegateを。そしてAppDelegateの関数:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
    if isShouldRotate == true {
        return Int(UIInterfaceOrientationMask.Landscape.rawValue)
    }
    return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}

そして最後に、ViewControllerAがランドスケープ状態を必要とするとき。それを行うだけです:ViewControllerA にpush / presentする前にisShouldRotatetrueに割り当てます。コントローラがviewWillDisappearでisShouldRotatefalseに割り当てることをpop / dismissするときに忘れないでください


0

私にとって、最上位のVCは、向きのオーバーライドを実装する必要がありました。最上位のVCが実装されていない場合、スタックを下にしてVCを使用しても効果はありません。

VC-main
    |
    -> VC 2
        |
        -> VC 3

VC-Mainのみがリッスンされ、基本的に私のテストではリッスンされます。


0

ここでもあなたはたくさんの答えがあるように見えます。私は方向付けを強制したかった後、デバイスの方向付けに戻りたいのですが[UIViewController attemptRotationToDeviceOrientation];、うまくいきませんでした。さらに複雑なことは、ある答えに基づいてshouldAutorotateをfalseに追加し、すべてのシナリオで正しい回転に戻すための望ましい効果を得ることができなかったことです。

これが私がしたことです:

彼のinitコンストラクタでコントローラを呼び出す前に、これは:

_userOrientation = UIDevice.currentDevice.orientation;
[UIDevice.currentDevice setValue:@(UIInterfaceOrientationPortrait) forKey:@"orientation"];
[self addNotificationCenterObserver:@selector(rotated:)
                               name:UIDeviceOrientationDidChangeNotification];

そこで、最後のデバイスの向きを保存し、向き変更イベントに登録します。方向変更イベントは単純です:

- (void)rotated:(NSNotification*)notification {
    _userOrientation = UIDevice.currentDevice.orientation;
}

そして見当違いで、私はuserOreintationとして持っている方向に強制的に戻すだけです:

- (void)onViewDismissing {
    super.onViewDismissing;
    [UIDevice.currentDevice setValue:@(_userOrientation) forKey:@"orientation"];
    [UIViewController attemptRotationToDeviceOrientation];
}

そして、これもそこになければなりません:

- (BOOL)shouldAutorotate {
    return true;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

また、ナビゲーションコントローラーはshouldAutorotateとsupportedInterfaceOrientationsに委任する必要がありますが、ほとんどの人がすでに持っていると思います。

PS:申し訳ありませんが、いくつかの拡張機能と基本クラスを使用していますが、名前はかなり意味があるので、概念は理解できます。あまりきれいではないため、さらに多くの拡張機能が作成されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.