If I have an ObservableObject
in SwiftUI I can refer to it as an @ObservedObject
:
class ViewModel: ObservableObject {
@Published var someText = "Hello World!"
}
struct ContentView: View {
@ObservedObject var viewModel = ViewModel()
var body: some View {
Text(viewModel.someText)
}
}
Or as a @StateObject
:
class ViewModel: ObservableObject {
@Published var someText = "Hello World!"
}
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
Text(viewModel.someText)
}
}
But what's the actual difference between the two? Are there any situations where one is better than the other, or they are two completely different things?
@ObservedObject
When a view creates its own
@ObservedObject
instance it is recreated every time a view is discarded and redrawn:On the contrary a
@State
variable will keep its value when a view is redrawn.@StateObject
A
@StateObject
is a combination of@ObservedObject
and@State
- the instance of theViewModel
will be kept and reused even after a view is discarded and redrawn:Performance
Although an
@ObservedObject
can impact the performance if the View is forced to recreate a heavy-weight object often, it should not matter much when the@ObservedObject
is not complex.When to use @ObservedObject
It might appear there is no reason now to use an
@ObserverObject
, so when should it be used?Note there are too many use-cases possible and sometimes it may be desired to recreate an observable property in your View. In that case it's better to use an
@ObservedObject
.Useful links:
Even though pawello2222's answer have nicely explained the differences when the view itself creates its view model, it's important to note the differences when the view model is injected into the view.
When you inject the view model into the view, as long as the view model is a reference type, there are no differences between
@ObservedObject
and@StateObject
, since the object that injected the view model into your view should hold a reference to view model as well, hence the view model isn't destroyed when the child view is redrawn.Apple documentation did explain why initializing with
ObservedObject
is unsafe.The solution is
StateObject
.At the same time, the documentation showed us how we should create data models in a view (or app/scene) when it can hold on to the truth, and pass it to another view.