Leave a rating/review
It’s time to learn about a few more of those data flow property wrappers I alluded to earlier in the course.
You’re familiar with State and Binding now.
To review, the difference between @State and @Binding is sort of like the difference between a value and a reference type.
State is like a value type, because it holds the data. Binding is like a reference type, because the data is stored somewhere else.
When you pass a State, you’re passing a copy of the data, whereas when you pass a Binding, you’re passing a reference to the data.
Something we didn’t talk about before is that State is only intended to work with value types. What happens when you have an actual reference type that you need to use with SwiftUI?
Fortunately, @State comes with a companion for reference types: @StateObject, which works like @State, but is made specifically for reference types.
Let’s take a look.
You’ve got a new sample project that you’ll work with for the rest of the course! It’s for keeping track of your favorite movies and rating them.
You’re borrowing it from another tutorial on the site, which I will link to in the author’s notes. Feel free to pause the video and have a look around if you want. I’ll be giving you a bit of a tour as you go, either way.
Let’s start by seeing how State is already being used in this app, just to review.
- Open up UserView.swift
There are two state properties in here. One to keep track of the user’s name, that one is bound to the TextField. And another for a favorite genre, which is bound to this GenrePicker view.
They’re laid out inside of a Form, a SwiftUI component you haven’t worked with yet, but it gives you this nice formatting if you’re building a.. well, a form!
So, this binding to “favoriteGenre” is passed into “GenrePicker”, which is another custom view in this project.
Take a look at it!
Open GenrePicker
There’s the other half of the State/Binding dance you’ve been using in this course.
This Binding attribute lets us pass in a binding to some data that is stored somewhere other than with this particular view.
Something you haven’t seen yet, is how this sort of data management lets you easily reuse views like this GenrePicker!
It’s not just used in the UserView to set the favorite genre.
- If you look at AddMovie.swift
- You’ll see GenrePicker is used again. A different binding is passed in, so you can pick a genre for a movie you’re adding to the app.
As I said a bit ago, all of these State properties you’ve been looking at are Value types. Structs, or in the case of Genre, an enumeration.
But over in MovieList.swift, the main view in the app This MovieStore is a class.
So, if you try a live preview here… And go to add a movie to the store…
Cats / Crime / 0.5
It won’t appear when you go back.
The movie has been added to the store.
You’ll see it as soon as you stop the live preview!
SwiftUI just doesn’t know it needs to update when movieStore changes.
So try out a new property wrapper attribute: @StateObject
@StateObject var movieStore = MovieStore()
When you use @State, SwiftUI takes control of the lifecycle of that property. It keeps the value of a @State property even when the view refreshes.
@StateObject will work just like that for reference types.
Try a live preview again… Add another movie…
Keanu / Comedy / 4.5
And hey, you can see it right away this time.
There is one more bit that is letting this “StateObject” attribute work.
Go and have a look at the MovieStore type.
And note that it conforms to “Observable Object”.