I'd like to implement a simple toggle to manually switch between dark and light modes. However, I don't know how to make my app refresh (redraw all windows) after I switch the toggle.
So far I found these answers Manually set light/dark mode in SwiftUI and Implement dark mode switch in SwiftUI App.
But both these solutions use SceneDelegate.shared
which is not recommended according to this answer.
var isDark: Bool = true {
didSet { SceneDelegate.shared?.window!.overrideUserInterfaceStyle = isDark ? .dark : .light }
}
Is there really no other option to implement this? I tried adding @Environment
variable but it works only once when the application starts. And I need my app to update the color scheme on toggle change.
.environment(\.colorScheme, settings.isDarkMode ? .dark : .light)
This is my toggle:
struct SettingsView: View {
var body: some View {
Toggle(isOn: $settings.isDarkMode) {
Text("Night mode")
}
}
}
In my model I have this variable:
@UserDefaultsBacked(key: UserDefaults.Keys.Settings.darkMode, defaultValue: false)
var isDarkMode: Bool
Just add .colorScheme
to your top View and add a color scheme variable (@State
, @Binding
, etc.). Whenever the variable changes the view (and children) update automatically.
struct ContentView: View {
@State var theColorScheme: ColorScheme = .dark
func toggleColorScheme() {
theColorScheme = (theColorScheme == .dark) ? .light : .dark
}
var body: some View {
ZStack { // or any other View
Color.primary // to make the change visible
Button(action: self.toggleColorScheme) {
Text("Toggle")
}
} .colorScheme(theColorScheme)
}
}
Note: if you want to update the color scheme of the whole presentation, you're better of using .preferredColorScheme
instead of .colorScheme
.