Leave a rating/review
Let’s talk a bit more about ObservableObject.
When your custom reference-type model conforms to ObservableObject, it provides a mechanism to bind an entire object and its properties to a View.
It’s ideal for data that you control, and for external models that need to be passed into a hierarchy.
The only requirement of ObservableObject is the objectWillChange property.
objectWillChange tells SwiftUI when to trigger a re-render of a View, that depends on your custom model. The good news is that you don’t have to implement that property yourself.
If you want to re-render views when a property value changes, all you have to do is annotate that property with the @Published attribute.
This will cause a notification to be sent to any Views subscribed to the data model reference type whenever their value change, triggering a re-render as a result.
This bit of SwiftUI magic uses the Combine framework behind the scenes. Combine is a framework for managing data flow inside of your app, but it’s out of the scope of this course.
If you’re interested, check out the Author’s Notes for some links to resources about Combine .
Once your model is an Observable Object with Published properties, how do you add it as a dependency on a View?
Instead of using the @State or @Binding attributes, use @ObservedObject.
That will tell SwiftUI that the data is an external reference type, and that it should subscribe for changes in the model that can be published at any time.
You’re back in the project.
You’re going to be making some changes to the UserView.
Right now, UserView sets a username and a favorite genre using @State.
- You can try that out in a live preview!
I’ll be Luna, and my favorite genre is Horror
But if you want to be able to pass these super important values elsewhere in the app, you need to do a little work.
You’re going to set up a UserStore class that keeps track of the current user’s data.
So, open up UserStore.swift!
We’ve already got a struct set up that represents a user, called “UserInfo”
struct UserInfo {
let userName: String
let favoriteGenre: String
}
Now we’ll make a class to store an instance of this user information.
- It’ll conform to ObservableObject. That will turn it into something that can be observed by SwiftUI.
- And to do that, we’ll need to import Combine
- The last step is to add a property for the user info.
import Combine
class UserStore: ObservableObject {
var currentUserInfo = UserInfo(userName: "Movie Lover", favoriteGenre: .action)
}
But a regular old property won’t do here. So, I’ve got another property wrapper for ya. “Published”
@Published var currentUserInfo: UserInfo?
@Published is what triggers any updates in observers of an ObservableObject.
Whenever a published property changes, observers are notified. By declaring currentUserInfo with the @Published property wrapper, setting a new value will update any views observing the UserStore.
OK, we’ve got an Observable Object, but you still need do the observing.
There are three places you could use this, in fact! But let’s start in MovieList
Add an observedObject userstore up at the top and just make a new one.
@ObservedObject var userStore = UserStore()
With that, you can add the user’s name up by the little profile icon
HStack {
Text(userStore.currentUserInfo.userName)
Image(systemName: "person.fill")
}
Now, you really also want this in UserView… So, go ahead and pass it in, now
leading:
NavigationLink(destination: UserView(userStore: userStore))
Then jump over to UserView And add a property so you can pass the object in
@ObservedObject var userStore: UserStore
You’re using the same property wrapper this time!
With that userStore available, you can actually grab the current user data and fill these views in when this userView appears
.onAppear {
userName = userStore.currentUserInfo.userName
favoriteGenre = userStore.currentUserInfo.favoriteGenre
}
- You can also uncomment these lines in the “updateUserInfo” method, and that will update the store based on the values you set for name and favorite genre.
You’ll need to pass a userstore into the preview, now, to keep it working.
static var previews: some View {
UserView(userStore: UserStore())
}
Go back to MovieList And try a live preview!
- Update your user data
- hit The Update button
- And see it show up in MovieList
The other place you could use the userstore is in the AddMovie view, to skip to our user’s favorite genre in the picker.
But then you’re passing this object around to two different views.
There might be a better option. Before that though, let’s go to a challenge.