iOS 18 からの画面サイズの変化を含めたUITraitCollectionへの対応方法
昨年、iOS 17からの画面サイズの変化への対応に関する記事を書きました。registerForTraitChanges(_:handler:)
を利用することが推奨されていましたが、 iOS 18 から別の方法が推奨されるようになりました。
この記事では、画面サイズの変化を含めた UITraitCollection
の変化にどう対応するかをまとめていきます。
AutoTraitTracking
iOS 18 から AutoTraitTracking
という仕組みが導入され、これを使うことが推奨されています。
AutoTraitTracking
は、上記のドキュメントに記載の関数内で UITraitCollection
へのアクセスがあると、その要素が変化すると自動的にその関数が呼ばれる仕組みです。
実際にどのような動きになるかを具体的なコードで見ていきます。
例えば以下のようなコードでは UITraitCollection
の変化だけでは viewWillLayoutSubviews()
は呼ばれません。
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
}
一方で以下のようなコードにすると、端末のライトモード・ダークモードの切り替えで viewWillLayoutSubviews()
が呼ばれます。
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
switch traitCollection.userInterfaceStyle {
case .unspecified:
case .light:
// ライトモードのレイアウト
case .dark:
// ダークモードのレイアウト
}
}
つまり、上記のドキュメントに記載のメソッド内で UITraitCollection
に応じたレイアウト更新を書いておくことで、自動的に UITraitCollection
の更新に合わせた対応が可能になります。
パフォーマンス的な話
今までと異なり、実装者が意識することはかなり減らせるようになっていました。
また、今回の記事を書くにあたり実際の挙動を確認すると viewWillLayoutSubviews()
など AutoTraitTracking
の対象になっているメソッドの実行回数が最適化されていることが分かりました。
例えば、ライトモード・ダークモードの切り替え時、viewWillLayoutSubviews()
が
iOS 17 では複数回呼ばれ
iOS 18 では traitCollection.userInterfaceStyle
へのアクセスが無ければ呼ばれない
という状況でした。
AutoTraitTracking
の導入によってこれらの関数でレイアウトの更新を行うようになるため、最適化されているのでは無いかと予想しています。
Discussion