I created a model like this
import Foundation
class Play:ObservableObject{
@Published var name:String="Tayle"
@Published var age:Int=12
}
It will be used in two views
For example:
struct Demo: View {
//1
@State private var play:Play = Play()
//2
//@StateObject private var play:Play = Play()
var body: some View {
NavigationView{
NavigationLink(destination: PlayNameView(play: play)){
Text("go to platnbame")
}
}
}
}
struct PlayNameView:View{
@ObservedObject var play:Play
var body: some View{
HStack{
Text("Hello,\(play.name)")
Button(action:{
play.name="iop"
}){
Text("change the name to:iop")
}
}
}
}
When I run the project,they have the same behavior. If @StateObject can do it,why choose @State
CodePudding user response:
@State
is a variable that is meant to hold value types such as Bools, Integers, Strings, structs and so on. Apple simply doesn't intend for @State
to be used on reference types such as ObservableObjects
, because once again, State is meant to store value types such as Int, not instances of classes. Apple says in the documentation,
Don’t use state properties for persistent storage because the life cycle of state variables mirrors the view life cycle. Instead, use them to manage transient state that only affects the user interface, like the highlight state of a button, filter settings, or the currently selected list item.
In short, you could use @State
variables to store, say, the number of times a user has clicked a button (since the app started), but not to store another ObservableObject
. Also, if you look at this, the article shows that using an Object with State will not cause the view's actual variable to update. This is because, again to quote the article,
Because we’re using a complex, reference type, the value of state itself never changes. While a property of state , num has changed, the @State property wrapper has no idea because it is only watching the variable state, not any of its properties. To SwiftUI, because it is only watching state, it has no idea that num has changed, and so never re-renders the view.
An @StateObject
, on the other hand, can store things such as ObservableObjects
. When the value of the Object changes, it will cause a view update, because all of it is observed by SwiftUI
. This will only happen with @Published
properties, though, and any change of those properties will, once again, cause the view to re-render. An important note, too: @StateObject
will create a new instance every time the view appears. If you need to persist the values, you would need to pass in the object from a more root view. Also, an @StateObject
can be changed from outside the view, whereas @State
variables are only intended to be private and local. For more information on why this is, refer to the Apple State
documentation: https://developer.apple.com/documentation/swiftui/state
Resources:
- https://story.tomasen.org/swiftui-difference-of-state-binding-environment-and-environmentobject-and-when-to-use-them-ff80699f45b7
- https://www.hackingwithswift.com/quick-start/swiftui/what-is-the-stateobject-property-wrapper
- https://www.hackingwithswift.com/quick-start/swiftui/whats-the-difference-between-observedobject-state-and-environmentobject
- https://levelup.gitconnected.com/state-vs-stateobject-vs-observedobject-vs-environmentobject-in-swiftui-81e2913d63f9#:~:text=Use @ State for very simple,than what @State can handle.
CodePudding user response:
For Objects use @StateObject property wrapper and for String, Int, etc use @State property wrapper.
@State: We use this property wrapper when we observe a property that is exists inside our ContentView.
@StateObject: We use this property wrapper when we are observing properties that exists outside of our ContentView like in our Object, we can observe that property changes by firstly conforming that class to ObservableObject Protocol and marking that property as @Published inside our Object.