13
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[SwiftUI]外観モードを変更する際の注意点

Posted at

外観モードの変更

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)
    }
}
13
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?