外観モードの変更
SwiftUIでは外観モードを
.preferredColorScheme(.light)
で変更できますが少し癖があるので紹介します。
1. 宣言に一番近いpresentationまでが変更される
これはドキュメントにも書いてあるのですが、preferredColorSchemeを呼ぶとその直近のpresentationよりも下のビューの外観モードが変わります。
アプリ全体が変更されるわけでは無いので注意
つまり、次のようなView構造の場合、Buttonは外観モードが変わらずListは動的に変更されることになります。
@State private var isPresented = false
@State private var isDarkMode = true
var body: some View {
Button("Show Sheet") {
isPresented = true
}
.sheet(isPresented: $isPresented) {
List {
Toggle("Dark Mode", isOn: $isDarkMode)
}
.preferredColorScheme(isDarkMode ? .dark : .light)
}
}
2. システム設定に準拠する場合はnilを渡す
ColorScheme
には.dark
,.light
があるのですが、システムの設定を使いたい場合はnilを指定します。
.auto
とか.system
ありそうで無いので注意しましょう。
3. sheetでシステム設定準拠をセットすると動作しない
これはバグな気がしますが、preferredColorScheme(nil)
を呼ぶとコントロールセンターからダークモードの切り替えをしても切り替わらなくなります。
この問題はiOS14.5で修正されていますが、sheet内で呼ぶ場合はiOS14.5以降でも発生します。
ワークアラウンドとしては、UIKitのUIWindowのoverrideUserInterfaceStyleを直接呼ぶことで変更することができます。
SwiftUIWorkaroundというライブラリを作ったのでささっと対応したい方は使ってみてください。
preferredColorSchemeと違い、アプリ全体のカラースキームが変更される点に注意してください。
struct ColorSchemeView: View {
@State var colorScheme: ColorScheme? = nil
var body: some View {
contentView
.workaround.preferredColorScheme($colorScheme)
}
}