【Swift】デバイスの向き変更を検知/取得する方法!UIDeviceOrientation型
この記事からわかること
- Xcodeでアプリの画面の向き変更を検知する方法
- デバイスの向き(縦/横/上向き)を取得するには?
- UIDeviceOrientation型とは?
- UIViewControllerのviewWillTransitionメソッドの使い方
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
Swift UIでデバイスの向きを取得する方法と変更を検知する方法をまとめていきたいと思います。
環境
- Xcode:14.2
現在の画面の向きを取得する
デバイス自体の現在の向きをコードで取得するにはUIDevice
クラスのorientation
プロパティを参照します。
var orientation: UIDeviceOrientation
UIDevice
インスタンスにはシングルトンのcurrent
プロパティからアクセスします。
使用例
UIDevice.current.orientation
UIDeviceOrientation型
取得できるのは列挙型UIDeviceOrientation
として定義されている値です。全部で7種類定義されており、縦向きや横向き、デバイスが水平で画面が上向きなどの状態を取得することができます。
使用例
func printOrientation(){
let orientation:UIDeviceOrientation = UIDevice.current.orientation
switch orientation{
case .unknown:
print("デバイスの向きが不明")
case .portrait:
print("デバイスの向きが縦向き")
case .portraitUpsideDown:
print("デバイスの向きが逆さま")
case .landscapeLeft:
print("デバイスの向きが左向き")
case .landscapeRight:
print("デバイスの向きが右向き")
case .faceUp:
print("デバイスが水平で画面が上向き")
case .faceDown:
print("デバイスが水平で画面が下向き")
default:
break
}
}
ここでいう左向き(landscapeLeft
)などはホームボタンが左にあることを示しています。
デバイスの回転を制限する
デバイスが回転した際にアプリの画面を一緒に回転させたくない場合は「TARGETS」>「Deployment Info」>「Device Orientation(デバイスの向き)」から設定可能です。「Device Orientation(デバイスの向き)」ではアプリに許容させたい向きを指定する設定項目なのでアプリ画面の向きを縦向きのみに固定するにはPortrait
のみにチェックを入れます。
デバイスの回転を検知する
デバイスの回転を検知するためにはNotificationCenter
クラスを使用します。NotificationCenter
クラスは異なるクラス間でイベントを通知するための機能を実装できるクラスです。デバイスの回転した際にイベント通知を受け取り、任意の処理を行わせることが可能になります。
observerOrientation
メソッドの引数forName
にUIDevice.orientationDidChangeNotification
を渡すことでデバイスの回転を観測し、通知として受け取ることが可能です。
func observerOrientation(){
NotificationCenter.default.addObserver(
forName: UIDevice.orientationDidChangeNotification,
object: nil,
queue: nil) { orientation in
print(type(of: orientation)) // Notification
print("デバイスの向きが変わったよ")
}
}
これでデバイスの回転を検知することができるようになりました。しかしorientation
で受け取れる値はNotification
型であり、縦向き/横向きで識別することはできませんでした。
UIDevice.beginGeneratingDeviceOrientationNotifications
公式リファレンス:beginGeneratingDeviceOrientationNotificationsメソッド
UIDevice
クラスにはbeginGeneratingDeviceOrientationNotifications
メソッドなるものが用意されています。これはデバイスの向きの変更に関する通知の生成を開始する役割を持っているメソッドです。また逆の役割(デバイスの向きの変更に関する通知の生成を終了)を持つendGeneratingDeviceOrientationNotifications
メソッドも用意されています。
addObserver
メソッドで既にイベントを検知できていますが、公式リファレンスを読むとこの2つのメソッドを適切なタイミングで正しく呼び出すのが正しいのかもしれません。
func observerOrientation(){
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(
forName: UIDevice.orientationDidChangeNotification,
object: nil,
queue: nil) { orientation in
print(type(of: orientation)) // Notification
print("デバイスの向きが変わったよ")
}
}
func stopObserver(){
UIDevice.current.endGeneratingDeviceOrientationNotifications()
}
実際に観測を開始してからendGeneratingDeviceOrientationNotifications
を実行するとイベントは検知されなくなります。
UIKItでデバイスの回転を検知する
UIKitのUIViewController
クラスでビューのサイズが変更されていることを検知できるviewWillTransition
メソッドを使用してビューの回転を検知することが可能です。
デバイスの向きはview.window?.windowScene!.interfaceOrientation
から取得することが可能です。
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { (context) in
// iOS12以前
// let newOrientation = UIApplication.shared.statusBarOrientation
// iOS13以降
guard let newOrientation = self.view.window?.windowScene!.interfaceOrientation else { return }
if newOrientation.isLandscape {
print("横向き")
} else if newOrientation.isPortrait {
print("縦向き")
}
}) { (context) in
// 画面の向きが変わった後の処理をここに追加
}
}
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。