问题
I'm currently getting familiar with SwiftUI and Combine frameworks. And I'm not really getting the difference between these two approaches. When we have to keep track of some data (say, a list of tasks), we can declare a @State variable, and it's change will automatically send notification and update current view. However, it looks like it can also be done this way:
class TaskList: ObservableObject{
//a list that's going to be modified and updated on different occasions
@Published var list: [String]
}
class TodoListView {
@ObservedObject var todoList = TaskList()
}
So, I missing a point - how are @State and @ObservedObject approaches different and which one is preferable under which circumstances?
Thanks!
回答1:
If you mark any variables as @State in a SwiftUI View and bind them to a property inside the body of that View, the body will be recalculated whenever the @State variable changes and hence your whole View will be redrawn. Also, @State variables should serve as the single source of truth for a View. For these reasons, @State variables should only be accessed and updated from within the body of a View and hence should be declared private.
You should use @State when you are binding some user input (such as the value of a TextField or the chosen value from a Picker). @State should be used for value types (structs and enums).
On the other hand, @ObservedObject should be used for reference types (classes), since they trigger refreshing a view whenever any @Published property of the ObservableObject changes.
You should use @ObservedObject when you have some data coming in from outside your View, such as in an MVVM architecture with SwiftUI, your ViewModel should be stored as an @ObservedObject on your View.
A common mistake with @ObservedObjects is to declare and initialise them inside the View itself. This will lead to problems, since every time the @ObservedObject emits an update (one of its @Published properties gets updated), the view will be recreated - which will also create a new @ObservedObject, since it was initialised in the View itself. To avoid this problem, whenever you use @ObservedObject, you always have to inject it into the view. The iOS 14 @StateObject solves this issue.
回答2:
The main difference is that @State is for structs, and @ObservedObject is for classes. Both @State and @ObservedObject achieve a similar thing, of updating you when something changes.
A struct changes when some property has been mutated, which means that it gets recreated, therefore the @State is updated. A class updates @ObservedObject when a property is changed - using @Published to listen for changes. When either @State or @ObservedObject is updated, the view body gets remade.
The question you are really asking here is when to use a struct vs a class if either would work in some situations.
In your case, since TaskList is only a basic data structure and doesn't require lots of properties you want to prevent from updating the view (by using/not using @Published), you should probably use a struct with @State instead.
来源:https://stackoverflow.com/questions/61361788/state-vs-observableobject-which-and-when