【Xcode】アプリ画面の向きを固定する方法!デバイスの回転と縦横識別

この記事からわかること
- Xcodeでアプリの画面の向きを固定する方法
- デバイスの回転を制御する
- PortraitやLandscapeとは?
- デバイスの向き(縦/横/上向き)を取得するには?
- 画面単位で制御するには?
- UITabBarControllerやUINavigationControllerで期待通りに画面が制御できない原因
index
[open]
\ アプリをリリースしました /
環境
- Xcode:16.0
- iOS:18.0
- Swift:5.9
- macOS:Sonoma 14.6.1
iOSアプリではデフォルトの設定で端末を横にした時に画面も横向きになる仕様になっています。そのため横向き画面の対応を行うか画面の回転を制御して横向きにならないようする設定を行う必要があります。今回は「画面の回転を制御する方法」をまとめていきます。

アプリ画面の向きを固定する方法
アプリが許容する画面の向きはXcodeの「TARGETS」>「Deployment Info」>「Device Orientation(デバイスの向き)」から設定可能です。例えば縦向きのみ(横向き対応しない)ようにしたい場合はPortrait
のみにチェックを入れます。

- Portrait:縦向き
- Upside Down:逆さま(※)
- Landscape Left:左向き
- Landscape Right:右向き
ちなみに英語の意味
- Orientation(オリエンテーション):1.適応(指導) 2.方向
- Portrait(ポートレート):1.肖像画 2.印刷用紙の縦置き
- Landscape(ランドスケープ):1.風景・景色 2.印刷用紙の横置き
Upside Down(逆さま)にならない端末
デフォルトではUpside Down(逆さま)
にチェックが入っていない状態ですが、これにチェックを入れても全ての端末で画面が回転時に逆さまになるわけではありません。これは公式に以下のように記載されています。
すべての iPadOS デバイスは、この方向をサポートしています。iPad のイディオムでは、これを有効にすることをお勧めします。iPhone 12 などのホーム ボタンのない iOS デバイスでは、この方向はサポートされていません。iPhone イディオムでは、これを完全に無効にする必要があります。
つまり「iPadとホームボタンのあるiOSデバイスは逆さま対応」、「iPhone12以降のホームボタンのないiOSデバイスは逆さま非対応」のようです。
またそれでも逆さまにならず、逆さまにするためには画面がサポートする方向を制御しているsupportedInterfaceOrientations
で明示的にall
やportraitUpsideDown
を指定してUpside Down
を許容させる必要があります。(デフォルト値がiPadの場合はall
ですがiPhone場合はallButUpsideDown
になっているため)
iPadでのデバイスの回転
「Device Orientation(デバイスの向き)」は「iPhone Orientation」と「iPad Orientation」に分かれているのでiPadにも画面の向きを適応させたい場合は「iPad Orientation」側のチェックを設定します。
iPadは逆さま対応もしているので期待通りの動作になります。
info.plistから設定する
「アプリの画面回転の許容する方向」は「info.plist」からでも設定することが可能です。「info.plist」に設定するためのキー「Supported interface orientations (iPhone)」を指定し、値(value)には先ほどと似たような設定値を渡します。

許容する向きの設定値
- Portrait(top home button):縦向き
- Portrait(top home button):逆さま
- Landscape(left home button):左向き
- Landscape(right home button):右向き
先ほどの「Device Orientation」と「Supported interface orientations (iPhone)」はリンクしているようなのでどちらかの設定をいじるともう片方も自動で修正されます。
※ iPad:Supported interface orientations (iPad)
キー
現在の画面の向きを取得する
デバイス現在の向きをコードで取得するにはUIDevice
クラスのorientation
プロパティを参照します。
取得できるのはUIDeviceOrientation
型で値はデバイスが水平で画面が上向きのfaceUp
や不明(unknown
)などを追加した7種類定義されています。
またデバイスの向きの変化は観測することも可能です。詳細は以下の記事を参考にしてください。
画面単位の回転制御
Xcodeからの回転制御の設定はアプリ全体に影響します。そのため特定の画面だけ横向き対応したい場合などには使用できません。画面単位ごとに回転を制御させるには先に少し登場しましたがsupportedInterfaceOrientations
をオーバーライドして許容する方向をUIInterfaceOrientationMask
型で返せばOKです。
コードから画面を回転させる
例えば任意のタイミングでコードから画面を回転させたい場合はsupportedInterfaceOrientations
の返却値を変数で保持させます。あとは任意のタイミングで切り替えるだけうまくいきそうですがこれだけでは期待通りに動作しません。サポートする画面が変化した際には明示的にsetNeedsUpdateOfSupportedInterfaceOrientations
メソッドを呼び出して通知する必要があります。
iOS16以前ではshouldAutorotate
というものがありこのプロパティでVCの画面の回転自体を制御していましたが今はDeprecatedになっておりsetNeedsUpdateOfSupportedInterfaceOrientations
への移行が推奨されています。
UITabBarControllerでの画面回転制御
UITabBarController
やUINavigationController
を使用している場合は上記の方法でも期待通りに動作しません。これはsupportedInterfaceOrientations
の仕様で表示画面のルートVCの設定が反映されるためです。そのためUITabBarController
の場合は以下のようにselectedViewController
のsupportedInterfaceOrientations
を返すように実装してあげれば切り替えた画面の画面制御が反映されるようになります。
extension
では期待通りに動作しませんでした。
UINavigationControllerの場合
UINavigationController
の場合はUINavigationControllerDelegate
プロトコルを使用する必要がありました。対象のVCに準拠させたらnavigationControllerSupportedInterfaceOrientations
をオーバーライドして明示的にTopViewController
のsupportedInterfaceOrientations
を指定することで期待通りに動作させることができました。
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。