I would like to switch the app between dark and light mode in the App’s settings. Apple offers this in some of their Apps so I know it is possible. There are 3 options:
- auto (use the device settings), 2) dark (override to dark), light (override to light)
This works most of the time, but fails with multicolour symbols.
The code to perform the switch is:
@main
struct ExperimentAppApp: App {
@AppStorage("isDarkMode") private var isDarkMode = "auto"
var body: some Scene {
WindowGroup {
ContentView()
.preferredColorScheme(isDarkMode == "light" ? .light : (isDarkMode == "dark" ? .dark : nil) )
}
}
}
The example code to toggle the settings and display the results is:
struct Settings: View {
@AppStorage("isDarkMode") private var isDarkMode = "auto"
var colors = ["auto", "dark", "light"]
var body: some View {
let currentMode = UITraitCollection.current.userInterfaceStyle
VStack(alignment: .leading) {
Text("The current device setting is: **(currentMode == .dark ? "dark" : "light")**")
HStack{
VStack(alignment: .leading) {
Picker( selection: $isDarkMode, label: Text("Display mode")
) {
ForEach(colors, id: .self) {
Text($0)
}}
}
}
VStack(alignment: .leading) {
HStack{
Text("Symbols: ")
Image(systemName: "suit.spade.fill").symbolRenderingMode(.multicolor)
Image(systemName: "suit.heart.fill").symbolRenderingMode(.multicolor)
}
Text("Symbols in string: (Image(systemName: "suit.spade.fill").symbolRenderingMode(.multicolor)) (Image(systemName: "suit.heart.fill").symbolRenderingMode(.multicolor))")
}
}
}
}
As you can see, this fails when the App-setting is opposite to the device-settings. E.g. device == dark, App == light. ===> the black symbol (♠️) does not display as it is an identical color to the background. However, it does display in light and dark mode properly when the device-setting happens to be the same as the app-setting, or when symbols are displayed using Image rather than in the Text.
Any ideas how to get round this problem without concatenating symbols and strings or anything awkward like that (translatability)?