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!
@StateObject and @ObservedObject have similar characteristics but differ in how SwiftUI manages their lifecycle. Use the state object property wrapper to ensure consistent results when the current view creates the observed object. Whenever you inject an observed object as a dependency, you can use the @ObservedObject.
When using observed objects there are three key things we need to work with: the ObservableObject protocol is used with some sort of class that can store data, the @ObservedObject property wrapper is used inside a view to store an observable object instance, and the @Published property wrapper is added to any ...
A property wrapper type that instantiates an observable object.
If you're finding it hard to remember the distinction, try this: whenever you see “State” in a property wrapper, e.g. @State , @StateObject , @GestureState , it means “the current view owns this data.” SPONSORED In-app subscriptions are a pain. The code can be hard to write, hard to test, and full of edge cases.
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 (struct
s and enum
s).
On the other hand, @ObservedObject
should be used for reference types (class
es), 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 @ObservedObject
s 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With