Your First iOS & SwiftUI App: An App from Scratch

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

Part 2: SwiftUI Data

18. Create a Model

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: 17. Intro to App Architecture Next episode: 19. Conclusion

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.

Transcript: 18. Create a Model

OK, let’s learn how we can put the theory of App Architecture into practice, by creating a simple data model for Bullseye.

To review, remember that we need three things: the target the user is aiming for, we need the current round, and we need the total score across all rounds. These will all be integer numbers.

OK - let’s open up Xcode and implement the Game struct.

Before we create our model, I wanna do a little bit of organization of our files here just as kind of a nice practice. We can keep everything nicely organized.

So, open up the navigator with the button on the upper left, and make sure you’re looking at the first tab for the project navigator.

Now, I’m going to click on the plus button in the lower left corner of the navigator and make a new group. I’ll call this group models.

This is where we’re going to put our model that we’ll be creating shortly, but let’s sort the rest of this code that we have as well.

We’ll create another new group and we’ll call it views. This time, select ContentView, then right click, and pick “New Group from Selection” and name it “Views”.

Right now we only have a single view in our app, but later on in this course, we’ll be creating more views that will live in this folder.

Finally let’s create one more group. Select the BullseyeApp file, and the Assets catalog, right click again and again pick “New Group from Selection”. Name this one “App”.

This is all of our kind of boiler plate other files that we need to create this app. I’m just going to minimize apps so I can just see views and models for right now.

Now, I’ll press Command + B which is a shortcut to build the app.

When you hit Command + R it built the app before running the app, but Command + B built the app without running it.

And this is just to make sure that I haven’t broken anything. I have one warning here, but we’ll worry about fixing this a little later.

All right, so now our files are nicely sorted.

Game.swift

We’re ready to add a file for our Game model.

Right click on models and click new file and that’ll create a new file within that group. And I’m going to choose the iOS Swift file template, click next.

And I’m going to name this Game.

This is a Swift file, and in the macOS finder you would see it with a .swift file extension. Xcode hides file extensions by default, but you can tell it’s a Swift file because of the little Swift to the left of the name.

This is mostly an empty file with just one line called import foundation. So we can start pretty much from scratch here. I’m going to delete this empty header at the top, but you can keep yours if you’d like.

Okay, so we’re going to create a new game struct.

So we do that by typing struct and then the name, which in our case is “Game”, and follow it up with a pair of curly braces.

struct Game {

}

It’s a Swift convention that names of types like structs and classes are capitalized, so make sure Game starts with a capital “G”

Inside here we’ll put the three properties that we need.

The first is the random target value.

So var for variable, which means it can change. And then we’re going to put in target for the name, colon. And this is going to be of type int, a plain integer number no decimal points. And set it to an initial value, any integer you like between 1 and 100, but I’ll do 37.

struct Game {
  var target: Int = 37
}

We also want the total score across all rounds. So score colon, it’s also an int and the initial score is going to be set to zero.

  var score: Int = 0

And then finally, we need a var for the current round, colon int. And the first round is going to be round one.

  var round: Int = 1

Okay, we’ll be adding a lot more to this game struct later on, but I think this is a good starting point. So let’s integrate this into our app.

ContentView.swift

So switch back to ContentView.swift, and scroll to the top.

So far, we have two properties here.

We need one more right now, one to store an instance of a Game.

This is also going to be a state variable because when the structure changes, for example, maybe the score changes we wanna our user interface to update accordingly. So it should be a state variable.

We should mark it private like we have the others. It also needs to be a variable, because it can change.

“game” is what we’re going to call this property. And it’s going to be of type game, with a capital G, just like we named the struct we created. And we’re going to set it to be a new game.

So the way we do this is capital-G Game and then a pair of parentheses. This creates a new instance of that template game.

@State private var game: Game = Game()

All right, so now that we have this, we can update our target label!

Right now the target label is hard-coded to 89. Instead of showing the hard-coded 89, we want to display the target from the game property.

To get to that, we’ll use the dot syntax, game.target.

But there’s an issue now, game.target is an integer and you can’t put an integer inside a text. So we need to convert the integer to a string.

You could do this with string interpolation, like we did in the alert. But if the only thing we want in the string is this int, there’s another way.

Type String and inside parentheses we can put in game.target. This is making an instance of a String out of that Int value.

Text(String(game.target))

Press Command + B to make sure that that builds. And builds okay, so I’m going to hit option Command + P to start up the preview again, since it stopped.

And notice that it used to be 89 but now it’s 37 and 37 is the initial value that we set up in our structure here. So, so far so good.

Remember that every class or struct you create can have data in the form of properties, and functionality in the form of methods.

We’ve figured out the three pieces of data we need for Bullseye, but what functionality do we need?

To start, maybe we can just calculate the points for a given guess. So we could create a method for that called points, and have it take a single parameter which is the slider’s value.

This is the first time we’ve written our own method in Swift, so let me take a moment to explain the syntax before we dive in.

Imagine you want to add a method that has some input - in other words, parameters - and an output - in other words, a return value.

To do this, you’d simply add a block of code that looks something like this.

Basically you use the keyword func, then you give your method a name, and then you enter an open and closed parenthesis.

In-between the parenthesis, you put any parameters, or input, that you want your method to accept. The format for this is the parameter name, a colon, then the type of the parameter.

You can create more than one parameter if you’d like; you would just separate them by commas.

After your list of parameters, you put a dash and a greater than sign. This is just two common characters put together but it has a fancy name: the Return Token.

After the return token, you indicate the type of object that you will return as the output of your method, like Int, Double, or Bool.

Inside the curly braces, you put all of the code you want to run in the method.

When you’re ready to return the output value, you enter the keyword return, then the value you want to return, like 999, 9.14, or true.

Now, parameters and return values are actually both optional. You can create methods with either or both of them missing. It just depends on what you need.

Now that we know what we need, we just need to code it up. So let’s switch back to Xcode!

Let’s add a method to calculate the points in the game.Swift. So, open up the Game swift file again.

Add a couple of new lines after these properties but before the closed curly brace.

And then to start the method, type in the keyword func to create a new method and type in points, which is the name of the method.

And in parentheses we’re going to put any parameters that this method takes. In our case, we want to check the slider value to see how close it is to the target value.

In this game struct, we already have access to the target, but we don’t have the slider value. So, add a single parameter, and call it slider value.

The type we want is and Int, so type colon int. And then we put the return token, which is the dash and then greater than sign. And that indicates, and what type of data does this method return.

And we’re also going to return an integer, which is the points that you’ve earned.

After that put open and closed curly brace. And inside here will be the code that we’ll run when we call this method. For now we’re going to just temporarily return 999 just so we can make sure this works.

func points(sliderValue: Int) -> Int {
  return 999
}

So now we can switch back to ContentView.Swift.

And let’s test out our new method. We want to show users what their score is after they’ve tapped the “Hit Me” button, as part of the alert.

We’re already showing the sliders value in a Text, here. We can show how many points were earned in the same Text.

When you have a bunch of text together it can get kind of hard to read, so I’ll show you how you can format that a little easier in Swift.

Inside the text, put three double quote marks in a row. Then start the text you want to show on the next line.

I like to put the quotes on their own line because it’s easier for me to read, but as long as the actual string starts on its own line, this will work.

Then, at the end, close it with three double quote marks, again, with those quote marks on their own line underneath the string.

Now, if we want a new line of text, we can just press return, and type “You scored xxx points this round.”

We actually want it to show the points, using our method. We can call the method right here inside the string if we use string interpolation again! Do that with a backslash, and a pair of parentheses.

Now inside the parens, type game to access our game model instance that we’ve created, then a dot, and then points. And remember that points, it takes a variable or a parameter called slider value and I select that here. To pass in the data, put it after the colon. In our case, the data we want to pass in is the Int version of the slider value, which we’ve already calculated and stored in the roundedValue variable..

Text(
  """
  The slider's value is \(roundedValue).
  You scored \(game.points(sliderValue: roundedValue)) points this round.
  """
)  

Okay, and that’s it.

So this is calling the points method on our game instance, passing in the rounded value. This method will return the number of points, which is right now hard-coded to 999.

So if we try it out in the canvas, just click “Hit me”, and there’s our longer alert message saying “you scored 999 points this round”, which proves that it’s calling our method and returning 999 successfully.

And it proves our multi-line string is working!