Search code examples
iosswiftswiftuicolor-schemeappstorage

SwiftUI Why is the color scheme of sheet not updating after the second time


I am trying to change the color scheme of a sheet in SwiftUI on a button click and use @AppStorage to store the selected scheme. It works exactly two times when clicking the button but after that the color scheme won't change anymore. I'm testing on iOS 15 if that matters. I noticed the print-statement in the onChanged of the @AppStorage property is also only called two times. Here is a minimal example that reproduces the problem:

import SwiftUI

struct settingsView: View {
   @State private var showSheet = false
   @AppStorage("isDarkMode") private var isDarkMode = false

   var body: some View {
       Button("Show Sheet") {
           showSheet.toggle()
       }
       .sheet(isPresented: $showSheet) {
           Button("Toggle Color scheme") {
               isDarkMode.toggle()
           }
           .preferredColorScheme(isDarkMode ? .dark : .light)
           .onChange(of: isDarkMode) { newValue in
               print("isDarkMode changed to \(newValue)")
           }
       }
   }
}

Solution

  • you could try this approach using .sheet(item: ...), works for me:

    struct Trigger: Identifiable {
        let id = UUID()
        var mode: Bool
    }
    
    struct ContentView: View {
        @State private var trigger: Trigger?  // <-- here
        @AppStorage("isDarkMode") private var isDarkMode = false
        
        var body: some View {
            Button("Show Sheet") {
                trigger = Trigger(mode: true)  // <-- here
            }
            .sheet(item: $trigger, onDismiss: {}) { val in  // <-- here
                Button("Toggle Color scheme") {
                    isDarkMode.toggle()
                }
                .preferredColorScheme(isDarkMode ? .dark : .light)
                .onChange(of: isDarkMode) { newValue in
                    print("isDarkMode changed to \(newValue)")
                }
            }
        }
    }
    

    .sheet(isPresented: $showSheet)... seems to have some serious limitations that is not well explained in the docs.