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.