Skip to main content

How to use @ObservedObject to manage state from external objects

About 3 minSwiftSwiftUIArticle(s)bloghackingwithswift.comcrashcourseswiftswiftuixcodeappstore

How to use @ObservedObject to manage state from external objects 관련

SwiftUI by Example

Back to Home

How to use @ObservedObject to manage state from external objects | SwiftUI by Example

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
}

Download this as an Xcode projectopen in new window

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:

  1. The ObservableObject conformance allows instances of this class to be used inside views, so that when important changes happen the view will reload.
  2. The @Published property wrapper tells SwiftUI that changes to score 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)
        }
    }
}

Download this as an Xcode projectopen in new window

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.

Similar solutions…
What's the difference between @ObservedObject, @State, and @EnvironmentObject? | SwiftUI by Example

What's the difference between @ObservedObject, @State, and @EnvironmentObject?
How to use @StateObject to create and monitor external objects | SwiftUI by Example

How to use @StateObject to create and monitor external objects
What is the @ObservedObject property wrapper? | SwiftUI by Example

What is the @ObservedObject property wrapper?
Observable objects, environment objects, and @Published | SwiftUI by Example

Observable objects, environment objects, and @Published
How to fix “Referencing initializer 'init(wrappedValue:)' on 'ObservedObject' requires that 'SomeType' conform to 'ObservableObject'” | SwiftUI by Example

How to fix “Referencing initializer 'init(wrappedValue:)' on 'ObservedObject' requires that 'SomeType' conform to 'ObservableObject'”

이찬희 (MarkiiimarK)
Never Stop Learning.