Your First iOS & SwiftUI App: An App from Scratch

Feb 13 2023 · Swift 5.7, iOS 16, Xcode 14

Part 2: SwiftUI Data

13. SwiftUI State

Episode complete

Play next episode

Next
About this episode

Leave a rating/review

See forum comments
Cinema mode Mark complete Download course materials
Previous episode: 12. Buttons & Actions Next episode: 14. SwiftUI Bindings

Get immediate access to this and 4,000+ other videos and books.

Take your career further with a Kodeco Personal Plan. With unlimited access to over 40+ books and 4,000+ professional videos in a single subscription, it's simply the best investment you can make in your development career.

Learn more Already a subscriber? Sign in.

Heads up... You've reached locked video content where the transcript will be shown as obfuscated text.

A key part of programming SwiftUI is state. Rather than start with the computer science definition of state, let's go with something that might be a little more familiar. The dashboard of a car. The most noticeable parts of a car dashboard are probably its ages in odometers. They show the car's current speed, fuel level, distance traveled and so on. Each of those is some kind of numeric quantity. Dashboards also have warning lights such as the low oil warning light, or the, it's time to take the car to the shop for some overpriced maintenance light. Each of these lights is either on, indicating that there's a problem that needs the driver's attention or off. This on, off, true, false information can be described as a Boolean value. So the information on a car's dashboard such as speed, fuel level, whether or not the car needs maintenance, taken all together is the visualization of the car's state. Keep in mind that the dashboard isn't the car's actual state, it's just a visualization of it. To see what I mean, think about what happens when the driver changes the car's state. For example, the driver presses the accelerator, and the car starts moving faster. The dashboard then updates to show the new speed. So the car state is how fast the car is actually moving, and the dashboard is just helping the driver visualize that fact. Internal circumstances can also change the car state. For example, as you drive, the car burns gas. The car state is how much gas is in the tank, and the dashboard hopefully updates the fuel indicator. But what happens if the car's state and dashboard aren't in sync? This actually happened to me with my first car, the fuel gauge was always at empty. And it was a big problem, I never knew how much gas I had. It turns out that this type of mistake is quite common while developing an app, that is your user interface might not accurately represent the internal state of your app. You may have sometimes come across an app with a bug like this. For example, an app says you have five new messages, but when you check, you actually have a different amount. One of the nice things about SwiftUI is that you're forced to develop your apps in such a way that your user interfaces and your state are always consistent, which prevents these frustrating types of bugs. At this point, the app state we're trying to add to Bullseye is very simple. Either the popup alert is visible or it's not. This is a Boolean value, which means it's either true or false. Do you remember how a few episodes ago you learned that class and struck templates, and the instances of those templates have data and functionality? Well, the Boolean value to keep track of whether the popup alert is visible or not is an example of some data that we need to keep track of on our ContentView struct and instance. So let's see how we can do this. We're working in ContentView again. I'm going to close the navigator and show the canvas. And start that up so we can see the preview. Now, right after this line it says struct ContentView: View. And before this line that says, var body: some view, we're going to add a new property. That's going to store whether or not alertIsVisible. So the way we'll do this is start by typing @State. @State is a special keyword that says, this is a state variable. Whenever a state variable changes, SwiftUI automatically recomputes the body, resolves the body of the view, and so the view and state variable are always in sync. So next we're going to put the word private, which is kind of a best practice when you're making a state variable. It says that, this variable is private to ContentView and other objects or structures should not be able to access it. Next, we're going to put the keyword "var" for our variable, which means this can change. And finally we're going to put the name of the variable, alertIsVisible. When you're making variables like this, it's a good practice to use camel casing. This is a fancy way of saying you start lowercase, and every time you need a new word, have the first character of that new word capitalized. It's just kind of a coding style thing with Swift. At the end we need to tell Swift what type of variable this is. So the variable that we're going to be using here is a Boolean, which means it can be one of two things, either true or false. And finally, we'll set an initial value. Remember that when the app starts up, the alert should not be visible. It's only when you tap "hit me," that the alert should be visible. So we want this variable to start as false, but space equals and then the initial value false. Now that the variable is set up and it's set to be false when the app starts, we want to make the button update that variable when it's pressed. So down in the buttons code where the print statement currently is, this is the code that gets run when the user taps the "hit me" button. So this is exactly when we want to set alertIsVisible to true. We can remove the print statement. And then changing the variable is as simple as typing "alertIsVisible" and the equal sign and then true. Remember that in SwiftUI, you're forced to develop your apps in such a way that your user interfaces and your state are always consistent. To do this, you keep track of your app state using variables marked with @State. Each state variable will have an initial value. For example, we set alertIsVisible to false. Then when the app starts up, iOS calls body to get a dashboard based on the current app state. For example, currently the body method returns the basic bullseye user interface, but doesn't show a pop-up. So far so good. But what happens when you set alertIsVisible to true. That's changing the app state. So it's important that the user interface is updated to be consistent. Well, since you already marked that variable with state, iOS will automatically refresh the body. So it's your job to make sure that body takes the app state into consideration, and displays an alert pop up if alertIsVisible is true. Let's see how we can do that. What we're doing next is still related to the button. This bit of code runs when the button is tapped. After this final curly brace, this is completing the definition of the button here. I want to call a method on the resulting button. So right after this line, hit "return" and then type in .alert. So we're calling a method on the button we just created. There are many similar methods with this name. The one we want has four arguments, titlekey, isPresented, actions and message. I'm going to put each of these on its own line, and the closing parens on its own at the end. Now we can fill each of these in. The title will appear at the top of the alert, and we can just enter whatever we wanted to say in quote marks. It's effectively making a text view for us with this. The next one is presented, wants us to pass in a variable that keeps track of whether the alert is currently visible or not. Well, good news, we already have such a property called "alertIsVisible." But there's one more thing, we have to put a dollar sign before this. And this is because we want to convert our state variable to a binding to the state variable. And you learn more about what bindings are in the next episode. But for now, just know that we need to put a dollar sign before the variable we want to use to trigger this alert. The third part is asking us for actions. This is a bit misleading because you might think that this is like the buttons action, but what it's really asking for is for you to put any buttons in here that you want to appear in the alert. Any button you put in here will close the alert by default without you having to code anything. If you don't put anything in here at all and just use a pair of empty curly braces, SwiftUI will create a button for you that just says "okay" on it. If you want that button to do or say something else, you can add it just like you would anywhere else, which means we can copy the button we already have, paste it in here and make it say something different. In the action, again, it will close the alert no matter what we do here. So for now, let's just print a message like "Alert closed." The final bit is a message. This is any other views you want to include in the alert to describe what it's about. This part isn't technically required for the alert to work, but let's put something in there. We already know the syntax we need to make the text, right? We put text and two parentheses, and we put what we want to say in quotes. How about, "This is my first alert." With this alert finished up, we can test the whole thing out. We don't even need to build to the simulator, we can try it out right here in the canvas. Make sure it's in live mode with the little play button highlighted in the lower left of the canvas, and click on the "hit me" button. The alert will pop up and there's that hello there title, and our message, "This is my first alert," and then the custom button that says "Awesome." Click the "Awesome" button, and the alert will close. And we're back to the main screen in the app. Remember that the print message isn't appearing in the console because we're using the canvas. So if something seems to be going wrong in the canvas interactions, always check the app running in a simulator. Then you can see any print statements you've set up. Congratulations, you finally made your app interactive. What you just did may have seemed like gibberish to you, but that shouldn't matter, we'll take it one step at a time. You can now strike off the next item from your programming to-do list. Show a popup when the user taps the "hit me" button. Take a little break, let it all sink in, and come back when you're ready for more. You're only just getting started.