问题
When I Googled "State vs ObservedObject" the first result was from Hacking with Swift and it said about @ObservedObject
:
This is very similar to @State except now we’re using an external reference type rather than a simple local property like a string or an integer.
Can I use @ObservedObject
to create persisted state? Is it as simple as @State
is for simple properties and @ObservedObject
is for complex objects, or is there more nuance to it?
回答1:
@ObservedObject
does not persist state
Can I use
@ObservedObject
to create persisted state?
On its own, you cannot. The Apple documentation has this to say about @State
:
A persistent value of a given type, through which a view reads and monitors the value.
But I found no mention of persistence with @ObservedObject
so I constructed this little demo which confirms that @ObservedObject
does not persist state:
class Bar: ObservableObject {
@Published var value: Int
init(bar: Int) {
self.value = bar
}
}
struct ChildView: View {
let value: Int
@ObservedObject var bar: Bar = Bar(bar: 0)
var body: some View {
VStack(alignment: .trailing) {
Text("param value: \(value)")
Text("@ObservedObject bar: \(bar.value)")
Button("(child) bar.value++") {
self.bar.value += 1
}
}
}
}
struct ContentView: View {
@State var value = 0
var body: some View {
VStack {
Spacer()
Button("(parent) value++") {
self.value += 1
}
ChildView(value: value)
Spacer()
}
}
}
Whenever you click on the value++
button, it results in a re-render of ChildView
because the value
property changed. When a view is re-rendered as a result of a property change, it's @ObservedObject
s are reset
In contrast, if you add a @State
variable to the ChildView
you'll notice that it's value is not reset when the @ObservedObject
is reset.
Using persisted state with @ObservedObject
To persist state with @ObservedObject
, instantiate the concrete ObservableObject
with @State
in the parent view. So to fix the previous example, would go like this:
struct ChildView: View {
let value: Int
@ObservedObject var bar: Bar // <-- passed in by parent view
var body: some View {
VStack(alignment: .trailing) {
Text("param value: \(value)")
Text("@ObservedObject bar: \(bar.value)")
Button("(child) bar.value++") {
self.bar.value += 1
}
}
}
}
struct ContentView: View {
@State var value = 0
@State var bar = Bar(bar: 0) // <-- The ObservableObject
var body: some View {
VStack {
Spacer()
Button("(parent) value++") {
self.value += 1
}
ChildView(value: value, bar: bar).id(1)
Spacer()
}
}
}
The definition of the class Bar
is unchanged from the first code example. And now we see that the value is not reset even when the value
property changes:
来源:https://stackoverflow.com/questions/59538786/what-is-the-difference-between-state-and-observedobject-can-they-both-be-used