Sponsor Link
環境&対象
- macOS Monterery beta 3
- Xcode 13 beta3
- iOS 15 beta
画面/デバイスの向き
iOS デバイスの画面の向きを確認するための仕組みとして、UIDevice.current.orientation があります。
画面の向きの種類等は、以下の記事を参照ください。
[SwiftUI] 縦横に柔軟に配置するレイアウトを作る
UIDevice.current.orientation が unknown 返す?!
UIDevice.current.orientation が unknown を返すケースがあります。加速度センサー等で検知できない時だそうです。
はまったケースは、
”Landscape にして起動したアプリで 起動直後は Landscape として正しい値が取得できるのに、そこから 別ビューを表示するために orientation をチェックすると unknown が返されてしまう” というケースでした。
画面のレイアウト調整に使用するために取得しているので、取得するタイミングを後回しにはできず、延々と調べてました。
unknown が返される時の workaround
(iOS14 以降では使えないのですが)回避策が見つかりましたので、メモしておきます。
UIApplication.shared.statusBarOrientation
(画面の向きではなく)アプリのインターフェースの向きをつかった判別も可能ということで、
UIApplication.shared.statusBarOrientation.isLandscape
というようなコードを使っても判別できたようです。
残念ながら、iOS13 で statusBarOrientation というプロパティが deprecated になってしまいました。
UIScreen.main.bounds
途方に暮れていたのですが、ベタな方法で判断してみることにしました。
デバイスのスクリーンは、UIScreen.main 経由でアクセスできるはずなので、UIScreen.main.bounds で画面の大きさが取得できるはずです。
ということで、UIDevice.current.orientation から unknown が返された時に、以下のように追加情報で判定することにしてみました。
// 前提:orientation は、UIDeviceOrientation 型で定義された変数で、
// この変数をみて、以降でレイアウト調整が行われます。
if UIDevice.current.orientation.isValidInterfaceOrientation {
orientation = UIDevice.current.orientation
} else {
// calc orientation from UIScreen.main.bounds.size (backup for UIDevice.current.orientation returns unknown)
orientation = UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height ? UIDeviceOrientation.landscapeLeft : UIDeviceOrientation.portrait
}
本来 landscape にも、landscapeLeft や landscapeRight があり、portrait にも、portrait と portraitUpsideDown がありますが、背に腹は変えられないということで、それぞれ landscapeLeft と portrait を決め打ちしてしまっています。
上記の制限はありますが、それ以外は、うまく動作しています。
もともと、自分の環境では、起動直後の特定のタイミングのみ unknown が返される状況でしたので、ほとんど UIDevice.current.orientation を使って処理されているので、本当に fallback 実装的な意味合いが強いです。
まとめ:UIDevice.current.orientation が unknown を返す時の対応方法
- iOS13以前であれば、UIApplication.shared.statusBarOrientation を使用する
- UIScreen.main.bounds の size をみて判断する
安定して取得できる方法をご存知の方は教えてください。
説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。
Sponsor Link