↪️

iOS 17 からの画面サイズ変化への対応方法

2023/06/11に公開

以下の WWDC のセッションを見て、画面サイズ変化への対応方法が iOS 17 から変えたほうが良さそうなのでまとめてみました。
ref:https://developer.apple.com/videos/play/wwdc2023/10057/

今までの画面サイズ変更への対応方法

iPhone における画面回転や iPad における SplitViewSlideOver 起動時のアプリの画面サイズの変更に対して、以下ののように対応していました。

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    if traitCollection.verticalSizeClass != previousTraitCollection?.verticalSizeClass {
        // 横方向のサイズが変わったときの処理
    }
}

この方法の問題点

この方法で問題なく動作はしていたのですが、画面サイズ変更と関係ない UITraitCollection の変化(例えばダークモードとライトモードの切り替え)でも呼び出されるため、パフォーマンスの面で問題がありました。
また、 iOS 17 からは UITraitCollection のカスタムが可能となったため、このメソッドが呼び出される頻度が増えることが予想されます。
そのような背景もあり、 traitCollectionDidChange(_:)iOS 17 以降では Deprecated になっています。
https://developer.apple.com/documentation/uikit/uitraitenvironment/1623516-traitcollectiondidchange

iOS 17 からの画面サイズ変化への対応

では iOS 17 からはどう対応するのでしょうか?
registerForTraitChanges(_:handler:) を利用します。
https://developer.apple.com/documentation/uikit/uiwindowscene/4138720-registerfortraitchanges

このメソッドでは、特定の UITraitCollection の変化のみを対象にして、処理を実行することができます。
例えば上記のコードと同等の処理を registerForTraitChanges(_:handler:) を利用して書いてみます。

override func viewDidLoad() {
    super.viewDidLoad()
    registerForTraitChanges(
        [UITraitVerticalSizeClass.self]
    ) { (self: Self, previousTraitCollection: UITraitCollection) in
        self.updateViews(sizeClass: self.traitCollection.verticalSizeClass)
    }
}

このように viewDidLoad() などのタイミングで registerForTraitChanges(_:handler:) を実行しておくことで、画面サイズの変化に対応して、処理を実行することができます。

Discussion