Using @AppStorage with @Observable
Written Jan 7, 2025
I wanted to persist values that I tracked in an @Observable
class using @AppStorage
and found pretty quickly out that it didn't work which was a bit of a disappointment.
After some googling I found a few workarounds and even a Swift package that adds another macro to patch the incompatibility.
However I found the more elegant solution in the excellent open source Ice Cubes repository. Here's a basic example based on that.
@MainActor
@Observable class Store {
class Storage {
@AppStorage("storage_key") var taylor = "swift"
}
private let storage = Storage()
var taylor: String {
didSet { storage.taylor = taylor }
}
init() {
taylor = storage.taylor
}
}
It can then be injected as an environment object.
struct ContentView: View {
@State var store = Store()
var body: some View {
StartView()
.environment(store)
}
}
To store the changes, add a @Bindable
to the store property.
@MainActor
struct StartView: View {
@Environment(Store.self) var store
var body: some View {
@Bindable var store = store // Create a mutable binding scoped within the body
TextField("Stored", text: $store.taylor)
}
}
Further reading: