Leave a rating/review
At this point, you’ve learned how you can add SwiftUI views to your app, either visually by using the SwiftUI canvas, or by tweaking the Swift code itself.
It’s time to take a deeper look at the code that you use to create SwiftUI Views and View Modifiers - but before you do that, it’s important to understand some programming theory about how this all works.
In this episode, you’ll learn about 3 key concepts of programming in Swift: instances, data, and methods. Then, we’ll take a deeper look at the code that the SwiftUI Canvas generated for you.
If you’re already familiar with the concepts of classes, structs, instances, properties, and methods and you feel comfortable with the SwiftUI code you’ve seen so far - feel free to skip this episode.
When you’re developing an app, programmers like to group related data and functionality into small pieces.
For example, let’s say you wanted to display a list of dogs in your app. To do this, you’d first define a template for what you need to know about each dog; such as its name and its breed.
Once that you have your template, you can create multiple instances of that template. You think of instances as a filled in verison of the template. For example you might create an instance for Dusty the Poodle, and an instance for Scampi the Maltese.
There are two main ways to define these templates in Swift: you can either use the keyword class
or you can use the keyword struct
.
In some programming languages, class
and struct
are radically different in functionality; usually you can do a lot more with classes
than you can structs
. But in Swift, structs
are very powerful and full featured, so the differences between the two are more subtle.
You’ll learn more about the differences in Programming in Swift: Fundamentals. But you don’t need to worry about that in this course; for now, you classes and structs as fairly interchangeable, and we’ll mostly be working with structs
.
You can think of your Swift app as a bunch of instances of class or struct templates that communicate with each other.
And believe it or not, you have experiences with both instantiating templates, and creating your own templates already.
For instantiating templates, think back to how you created an instance of the Button template. You also created an instance of a Text template that says “Hit Me”, which you put inside the Button instance.
You also created your own template. Think back to how you created your own struct called ContentView, and you defined what its body should look like.
As you can see, iOS provides many templates for you, such as the Button or Text Views, and sometimes you have to create your own, like you did for ContentView.
A class or struct, or an instance of a class or struct, can have both data and functionality. For example, consider the “Hit Me” button in your app.
-
First, it has some data, such as the View to display inside, its position on the screen, its width and height, and so on.
-
Second, it has some functionality, such as the ability to recognize when the user taps on it, highlight itself when tapped, and trigger an action in response.
The part that provides functionality is commonly called a method. You will also see the term function used in Swift; a method is simply a function that belongs to an instance.
You’ve already used a few methods in Bull’s Eye so far. Remember when you made the Text view bold, and set its kerning? Thoese were examples of calling a method on a Text instance.
You can tell it’s calling a method because the syntax to call a method is to take the instance, then put a period (.
), then put by the name of the method. Afterwards, you put parenthesis, and then any parameters to the method, which you can think of as ‘input’ to the method.
The first method here, bold, takes no parameters. But the second method, kerning, takes one parameter: which is the kerning that you want between the characters.
The methods you’ve used so far, like bold or kerning, have been written for you by the engineers at Apple. Later on in this course, you’ll learn how you can write your own methods, too.
The concept of methods may still feel a little bit weird to you, so let’s take a look at an example.
You (or at least an instance named “You”) want to throw a party. You clean the room, and put on some music. But you forgot to buy some cookies!
Fortunately, you’ve invited the instance named Steve who happens to live next door to a convenience store. So you call a method on Steve asking him to bring you some cookies.
The computer now switches to the instance Steve and executes the commands from his buyCookies() method, one by one, from top to bottom.
When the buyCookies() method is done, the computer returns to your throwParty() method and continues with that, so you and your friends can eat the cookies that Steve brought back with him.
The Steve instance also has data. Before he goes to the store he has money. At the store he exchanges this money data for other, much more important, data: cookies! After making that transaction, he brings the cookies back over to the party, and you add them to your drink and snack table. If he eats the cookies all along the way, well - your program has a bug.
Finally, let’s talk about data and properties.
Throughout this video, I’ve been using the term data to refer to the information an instance needs to do its job.
In Swift, the way you store data on an instance is through something called a property
. And there are two main types of properties provided by Swift.
First, there are stored properties. This is when you want the instance to simply store a piece of data for you, like the subtotal for a bill, or the tax that you need to pay.
Second, there are computed properties. This is when you want the instance to run some code you write in order to calculate a piece of data. For example, you might want to make a computed property to calculate the total bill, based on the subtotal and tax stored properties you created earlier.
OK, that was a lot! Let’s review the key point.
The most important thing to remember from this lecture is that your app is made up of instances of classes or structs, and that these contain two things:
- first, data, like the money to buy ice cream with
- and second, methods - like the steps involved in buying ice cream
Instances can look at each other’s data - well, to some extent at least. After all, Steve may not approve if you peek inside his wallet.
You can also ask other instances to perform their methods, like how you asked the text view to set its font weight to bold. Asking instances to perform their methods is how you get your app to do things.
Let’s take a deeper look at the code that we’ve written so far. You’ll see that it already includes examples of of instances, data, and methods!
Let’s start with instances.
struct ContentView: View {
Here we’re defining a template for an instance using the struct
keyword, called ContentView
. You can say this line in plain English as “We’re defining a template for an instance called ContentView
, that is a View
”.
If we switch to BullsEyeApp.swift, here’s the line that creates an instance of a ContentView
, based on that template:
ContentView()
Now let’s move onto properties. Back in ContentView.swift, we can see that ContentView
defines a computed property called body
.
var body: some View {
body
is a property of type some View
. The body acts as the container for all the instances on the screen that ContentView
represents.
var
is short for variable, which means two things: 1. It’s a container for data and 2. Its contents can change.
This line, translated from Swift to plain English, means “This is the definition of a variable named body
, and it’s a some View
.” So basically, this is letting ContentView
know what to display as its main body: which is all of the views that you can see on the screen inside a VStack
.
Unlike ContentView
, whose definition says that it’s a View
, the definition of body
says that it’s a some View
. The some
in front of View
broadens the possibilities for body
. Without getting into too much detail for now, it means that body can contain either a View
or something that behaves like a View
. This means that it could be an instance that isn’t exactly a View
, but it has the same properties and methods as View
.
The contents of the body
computed property are defined by these lines:
VStack {
Text("🎯🎯🎯\nPUT THE BULLSEYE AS CLOSE AS YOU CAN TO")
.bold()
.kerning(2.0)
.multilineTextAlignment(.center)
.lineSpacing(4.0)
.font(.footnote)
Text("89")
HStack {
Text("1")
Slider(value: .constant(50), in: 1.0...100.0)
Text("100")
}
Button { } label: {
Text("Hit me")
}
}
And in particular, all of the lines here where we’re applying view modifiers are examples of calling methods. For example, this first line calls the Text
object’s bold()
method. When you call this method, bold()
bolds the text, and returns a new, bolder Text
instance.
Similarly, these are all examples of other methods that we’re calling on the Text instance to apply other view modifiers. As you can see, some of these pass values to the methods, which as I mentioned earlier are called parameters. For example, here we pass the value 2.0 to the kerning method.
OK! As you’ve seen, you already have some experience working with instances, data, and methods in Swift and SwiftUI.
First, you have experience with instances. For example, you’ve created — or as programmers would say, instantiated — an instance of the ContentView
struct to display a bunch of views on the screen.
Second, you have experience with data. For example, you’ve created a body
property that keeps track of an important piece data for the ContentView
instance: that is, the view to display on the screen, which is a VStack
with a bunch of other views inside.
Finally, you have some experience with methods. You called several methods on the Text
instance: including bold()
, kerning
, and many more.
Wow - that was a lot to cover. Don’t worry if you didn’t get everything right away or if you have trouble understanding some of the syntax or terminology; there’s a lot concepts here that may be brand new to you.
We’ll review these concepts again and again throughout this course and the rest of the courses in our learning path until they feel like second nature. Again: it’s all about learning via repetition.