How to use @ObservedObject to manage state from external objects
How to use @ObservedObject to manage state from external objects 관련
Updated for Xcode 15
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 properties inside an observed object that should cause views to update when they change.
Tips
It is really important that you use @ObservedObject
only with views that were passed in from elsewhere. You should not use this property wrapper to create the initial instance of an observable object – that's what @StateObject
is for.
As an example, here's a UserProgress
class that conforms to ObservableObject
:
class UserProgress: ObservableObject {
@Published var score = 0
}
I know that doesn't look like much code, but that's because SwiftUI is doing a remarkable amount on our behalf! There are two things that matter in there:
- The
ObservableObject
conformance allows instances of this class to be used inside views, so that when important changes happen the view will reload. - The
@Published
property wrapper tells SwiftUI that changes toscore
should trigger view reloads.
We can use that UserProgress
class with code like this:
class UserProgress: ObservableObject {
@Published var score = 0
}
struct InnerView: View {
@ObservedObject var progress: UserProgress
var body: some View {
Button("Increase Score") {
progress.score += 1
}
}
}
struct ContentView: View {
@StateObject var progress = UserProgress()
var body: some View {
VStack {
Text("Your score is \(progress.score)")
InnerView(progress: progress)
}
}
}
As you can see, other than using the @ObservedObject
property wrapper with progress
, everything else more or less looks the same – SwiftUI takes care of all the implementation details for us.
There is one important difference, though: the progress
property isn't declared as private. This is because bound objects can be used by more than one view, so it's common to share it openly.
Remember, please do not use @ObservedObject
to create instances of your object. If that's what you want to do, use @StateObject
instead.