Recipe editor is the app shared to demonstrate how to use @State and @Binding
This project they share is fluffy for a Recipe Editor. It has recipes which are stored in JSON, an option to ‘favorite’ a recipe and a way to add new recipes. Regrettably, new recipes are not saved nor are favorites persisted. If I favorite a different recipe or add a new one, once I turn the app off it will all be gone, with the app in this form.
There are a few property wrappers we should understand from this lesson:
State & Binding I mentioned above, we also have @StateObject, @EnvironmentObject, @ObservedObject. There is a class they created that manages Images. It was awkward where they mention the solution is a hack which should not be used in real life. The other class is the RecipeBox, which is an ObservedObject.
I need to take a moment and just say it- this lesson had me confused most of the time, like what is the best use of @State? I prefer how they presented it here. The intro was more gentle, clear and with a purpose. Anyhow, I wanted to take a step back and explain the relationship of @State and @Binding:
You have a view, which has properties. These properties impact the way our view looks with regard to a switch, some color or text, whatever. Let’s say that one of our subviews would display different content based on one of our properties’ result. The first line in the docs states : Use state as the single source of truth for a given value type that you store in a view hierarchy. So here we have this important piece of information, the PlayButton.isPlaying (as in the docs), we will showFavoritesOnly (as in the first tutorial), and in this tutorial we will configure the Recipe Editor, show delete confirmation on the View level, and on the App level we select a Sidebar Item & select a Recipe ID. I guess I didn’t have that 💡 moment over the past week reading the code, running breakpoints, and I’m sort of fuzzy on if @Binding is too heavy of a ‘hammer’ for the same task.
Docs on @State have a comment regarding @Binding: If you pass a state property to a subview, SwiftUI updates the subview any time the value changes in the container view, but the subview can’t modify the value. To enable the subview to modify the state’s stored value, pass a Binding instead. Okay, that seems clear. reading further, Like you do for a StateObject, declare State as private to prevent setting it in a memberwise initializer, which can conflict with the storage management that SwiftUI provides. Unlike a state object, always initialize state by providing a default value in the state’s declaration, as in the above examples. Use state only for storage that’s local to a view and its subviews. A whazza? @StateObject we have in our sample app, fuzzy on how it relates but here we are!
Pivoting back to the app, looking at RecipeBox it behaves as our data fetcher. Inside RecipeBox, we can see it manages the recipes and there is a method to pull data from JSON. It makes me curious: if we want to write to JSON in our RecipeBox, would this remain a @StateObject 🤔