From the course: Complete Guide to SwiftUI

Updating models from views

- [Instructor] Our next navigation view is sheets. But before we do, we have a small diversion to make. Sheets work on the same principle as alerts, you have a presenting variable. But unlike alerts, any view can be presented, allowing for customization to the view. That means we need a view to put here. And so we have a nice pretty view. I made you one that's called Order Detail View, which you'll find in the Assets folder for this chapter and video. So I'm going to go ahead and import that by going into here. And then let's pull it up again. And we're going to take the Order Detail View, I'm just going to drag it in here, put it down on the bottom next to model code here. We're going to copy files of the destination. The target is HuliPizza, so I'll go ahead and finish. And I want to look at this a little bit because it's got some interesting things going on. First of all, with the preview on, you can see what I did here, is pretty much it's a cleaned up version of what we had done earlier with Order Item View, but it has a few extra things. It's got the buttons, it's got some more information, and we put a gradient in there as well to make it look nice and pretty. Now the big change to this view is actually behind the scenes. It's how I deal with the model, and a problem with state and binding variables, I wanted to show you. We dealt with this before in Order Item View, but now we're going to have a few new parts. Now this view is meant to work with both Order View and Menu Item View, and we're going to make sheets for both of those. For Menu Item View, it adds a pizza, but on order view, it changes the pizza. Now, if I made the control here using the variable, Binding Order Item, I could run into a little bit of a problem. For order view, because it's binding, it's going to then send this back to its super view. That super view may actually use that information. I may not want all of this to start to make changes to my super view while I'm having the user fix this. It also means down here we have the Order and Cancel buttons. I only want this information to reflect in the rest of my app after I hit Order. I may want to abandon it all with Cancel. So I want to hold onto this until I hit Order and completely abandon it when I hit Cancel, and leaving this binding variable the way it is, it's going to just throw it up there and it's not going to work, right? So we have to follow a way of doing that, and that's what I wanted to show you. We sort of set this up earlier when we did it with Menu Item View, but we're adding a couple more things with this update business. Okay? So first thing I did is I have a bunch of private variables. These controls are all local. They're not going to be affecting the super view. So they're all state variables and they're all being controlled locally. And then what I end up doing is I then initialize, like I do here, some of those items so that the stuff that I'm getting from the outside will come into this app, and I set up Order Item, present sheet in new order as internal variables using an initializer, because I have binding here. Okay? So what we have to do, as we talked about earlier, we have to use an initializer because we have binding and then set it up accordingly. Then once we do that, I'm now going to update the rest of these state variables. And to do that, I want to make sure they're all initialized first. So I wait till after the initialization and then down here on onAppear, I go ahead and put in the pizza crust, the quantity, the double ingredient, name, and comments, and I initialize my controls. Now that I have that done, I'm ready to use it. And the way I use it, and you go up here, you'll see a function called Update Order, and Update Order will now change when I run it and put all of those state variables into my binding variable, Order Item. And I'll do that when I hit the Order button, and I won't touch this if I hit the Cancel button. Now you'll notice here one other thing: And this variable, newOrder. It's a flag for a new pizza. Generally, the init will default to true, as you can see here in the initializer. So there's no problem when I use this with adding an order, but when I change an order, I'll set this to false and adding an additional pizza won't happen. So I've got a way of making sure that I know when I'm changing and what I'm not changing in this pattern. It's a good one to remember when you're dealing with input views that have binding variables, you don't want to change unless you press a button. Store your controls in a local state variable and then send them to the binding variable only when you're ready to do so.

Contents