Hi folks
I'm playing with the new @AppStorage wrapper because I'm considering using it to store some simple application state data.
I've created a custom class, which conforms to ObservableObject, and RawRepresentable, and it all works fine if I do all my work in a single view.
If I invoke a subview, and pass in the @AppStorage object as an environmentObject, I can read data from it, but updates to the data never propagate back to the underlying storage.
Here is a simplified reproducer, using the new @main/App lifecycle. I would be thrilled if anyone can help me figure out what's wrong:
I'm playing with the new @AppStorage wrapper because I'm considering using it to store some simple application state data.
I've created a custom class, which conforms to ObservableObject, and RawRepresentable, and it all works fine if I do all my work in a single view.
If I invoke a subview, and pass in the @AppStorage object as an environmentObject, I can read data from it, but updates to the data never propagate back to the underlying storage.
Here is a simplified reproducer, using the new @main/App lifecycle. I would be thrilled if anyone can help me figure out what's wrong:
Code Block Swift // // ContentView.swift // AppStorageTest // // Created by Chris Jones on 25/06/2020. // import SwiftUI import Combine @main struct AppStorageTestApp: App { var body: some Scene { WindowGroup { ContentView() } } } class Person: RawRepresentable, ObservableObject { @Published var name: String @Published var age: Int // RawRepresentable var rawValue: String { get { let value = "\(name):\(age)" print("Returning raw value: "+value) return value } } required init?(rawValue: String) { if rawValue == "" { print("Initialised with empty rawValue, setting defaults") self.name = "Jonny Appleseed" self.age = 42 return } print("Initialising with rawValue: \(rawValue)") let parts = rawValue.split(separator: ":") self.name = String(parts[0]) self.age = Int(parts[1])! } } struct ContentView: View { @AppStorage("person") var person: Person = Person(rawValue: "")! var body: some View { // Swap this subview out for the VStack{} from ContentSubview and this all works ContentSubview().environmentObject(person) } } struct ContentSubview: View { @EnvironmentObject var person: Person var body: some View { VStack { TextField("Name: ", text: $person.name).padding() TextField("Age: ", value: $person.age, formatter: NumberFormatter()).padding() } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView().environmentObject(Person(rawValue: "")!) } }