If I create an ObservableObject
with a @Published
property and inject it into a SwifUI view with .environmentObject()
, the view responds to changes in the ObservableObject as expected.
class CounterStore: ObservableObject {
@Published private(set) var counter = 0
func increment() {
counter += 1
}
}
struct ContentView: View {
@EnvironmentObject var store: CounterStore
var body: some View {
VStack {
Text("Count: \(store.counter)")
Button(action: { store.increment() }) {
Text("Increment")
}
}
}
}
Tapping on "Increment" will increase the count.
However, if I don't use the EnvironmentObject
and instead pass the store instance into the view, the compiler does not complain, the store method increment()
is called when the button is tapped, but the count in the View
does not update.
struct ContentViewWithStoreAsParameter: View {
var store: CounterStore
var body: some View {
VStack {
Text("Count: \(store.counter) (DOES NOT UPDATE)")
Button(action: { store.increment() }) {
Text("Increment")
}
}
}
}
Here's how I'm calling both Views:
@main
struct testApp: App {
var store = CounterStore()
var body: some Scene {
WindowGroup {
VStack {
ContentView().environmentObject(store) // works
ContentViewWithStoreAsParameter(store: store) // broken
}
}
}
}
Is there a way to pass an ObservableObject
into a View as a parameter? (Or what magic is .environmentalObject()
doing behind the scenes?)
It should be observed somehow, so next works
struct ContentViewWithStoreAsParameter: View {
@ObservedObject var store: CounterStore
//...