Search code examples
swiftuiproperty-wrapperappstorage

SwiftUI - How to access and update an @AppStorage var from multiple Views?


Is there a better way to use @AppStorage variables than through a Binding as shown below?

Is there a way to access UserDefaults in the environment?

struct ContentView: View {
    @AppStorage("darkMode") var darkMode = false

    var body: some View {
            SubView(darkMode: $darkMode)
        }
    }
}

struct SubView: View {
    @Binding var darkMode: Bool
    var body: some View {
        Text("Dark Mode is \(darkMode == true ? "on" : "off")")
    }
}

Solution

  • By using @AppStorage in different views you still access the same UserDefaults.standard storage (unless you explicitly specify the suiteName).

    Which means you can just use the @AppStorage directly in the subview.

    struct ContentView: View {
        @AppStorage("darkMode") var darkMode = DefaultSettings.darkMode
    
        var body: some View {
            VStack {
                Button("Toggle dark mode") {
                    self.darkMode.toggle()
                }
                SubView()
            }
            .colorScheme(darkMode ? .dark : .light)
            .preferredColorScheme(darkMode ? .dark : .light)
        }
    }
    
    struct SubView: View {
        @AppStorage("darkMode") var darkMode = DefaultSettings.darkMode
    
        var body: some View {
            Text("Dark Mode is \(darkMode == true ? "on" : "off")")
        }
    }
    
    enum DefaultSettings {
        static let darkMode = false
    }
    

    Note: the default darkMode value is extracted (to the DefaultSettings enum) so you don't repeat false in each view.


    Alternatively you can inject @AppStorage directly to the environment. See: