ARTICLE AD BOX
I have a singleton Settings object defined in an iOS app, owned by the root ContentView (using the @State property wrapper). Here is ContentView (with extraneous bits removed):
struct ContentView: View { @State private var showingSettings = false @State private var settings: Settings = Settings(/* default values here */) var body: some View { Button("Settings", systemImage: "gear") { showingSettings = true } .tint(settings.theme.buttonColor) .sheet(isPresented: $showingSettings) { SettingsView(isSettingsVisible: $showingSettings, settings: $settings) } } }Here is that Settings class (again, with some unrelated bits removed):
@Model class Settings { var themeId: String = "Summer" var theme: Theme { Theme.AllThemes.first { $0.id == themeId } ?? Theme.AllThemes[0] } init(themeId: String) { self.themeId = themeId } }Settings is defined with @Model because it is persisted using SwiftData, but I don't think that is related.
There is a child view, SettingsView, rendered as a sheet by the root view, that allows you to manipulate the various settings in the app:
struct SettingsView: View { @Binding var isSettingsVisible: Bool @Binding var settings: Settings var body: some View { NavigationStack { Form { Picker("Theme", selection: $settings.themeId) { ForEach(Theme.AllThemes) { theme in Text(theme.id) .tag(theme.id) .padding() .background(theme.buttonColor) .foregroundColor(Color.white) .cornerRadius(8) } } .pickerStyle(.inline) } .navigationTitle("Settings") .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Close") { isSettingsVisible = false } .tint(settings.theme.buttonColor) } } } } }As you can see, the "Close" button in the .toolbar uses a property of the Settings object to determine which background color it should use. However, changing the themeId in the picker doesn't cause the button background to change.
I can see other elements of the UI (by dragging the sheet down to reveal the parent view) updating right away in the background and correctly reflecting the change in theme as soon as the theme is changed. In addition, if you change the "Close" button in the toolbar to have settings.themeId as its label, then the label changes, but so does the background color (as intended).
Here is the Theme struct:
struct Theme: Identifiable, Hashable { var id: String var buttonColor: Color var backgroundColors: [Color] static let AllThemes = [/* pre-load the theme objects here */] }Why does the toolbar button's background color not update unless you also reference some other property of Settings? Is it because settings.theme is a computed property? Or am I just making a subtle binding mistake somewhere?
