I am making a game with a minimal color scheme. I store the colors that I use as computed static var
‘s in an enum so that I can call them in any view. I am trying to make a secondary color scheme (colorblind). My code looks like this:
enum GameColors {
static var exampleColor: Color {
!UserDefaults.standard.bool(forKey: GamePrefs.colorBlindMode) ? Color.green : Color(red: 0 / 255, green: 213 / 255, blue: 255 / 255)
}
}
enum GamePrefs {
static let colorBlindMode: String = "colorBlindMode"
}
My settings menu is called in my main menu view like so:
struct MainMenuView: View {
@State var settingsClicked: Bool = false
var body: some View {
VStack {
Button {
settingsClicked.toggle()
} label: {
Text("Settings")
.foregroundColor(GameColors.exampleColor)
}
if settingsClicked {
SettingsView()
}
}
}
}
struct SettingsView: View {
@AppStorage(GamePrefs.colorBlindMode) var colorBlindMode = false
var body: some View {
Toggle(isOn: $colorBlindMode) {
Text("Color Blind Mode: (colorBlindMode ? "On" : "Off")")
.foregroundColor(GameColors.exampleColor)
}
}
}
When I toggle colorBlindMode
, only SettingsView
‘s colors are updated, the color of the main menu does not change unless I interact with it. How do I get both to update?
I’ve tried binding the @AppStorage
property wrapper to no success.
3
Answers
After reading a bit more about what causes SwiftUI to reload a view, and a whole lot of testing different methods, I believe that the simplest way to solve this problem is to introduce a new
@State
variable which you must use somewhere in the parent view:Passing this state from the parent view to the child view allows the child to force reloads on the parent at will.
You could try this approach, using
@AppStorage
and.onReceive
inMainMenuView
,to ensure
GameColors.exampleColor
is updated/received in theMainMenuView
whileclicking in the
SettingsView
.The reason your color does not change is because of your
MainMenuView
is not refreshing when you press the toggle. Only yourSettingsView
is refreshed. So you would need something to notify yourMainMenuView
that something has changed.To do so you can add another AppStorage to your
MainMenuView
and force your view to refresh by creating a dependency on this property.