Programming in Swift: Fundamentals

Oct 19 2021 · Swift 5.5, iOS 15, Xcode 13

Part 5: Functions & Named Types

38. Structures

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: 37. Challenge: Functions Next episode: 39. Challenge: Structures

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.

Notes: 38. Structures

Update Notes: The student materials have been reviewed and are updated as of October 2021.

Transcript: 38. Structures

In this exercise, we’ll begin our tour of structures in Swift. You’ll usually hear them called “Structs”.

Structs–like tuples–allow you to group a set of related data together. For example, maybe you want to store a person’s first name, last name, and favorite color into a single unit. In a Struct, those bits of data are called properties. They represent what a structure “has”.

Unlike tuples, structures can also contain methods. Methods represent what a structure “does”. Remember, methods are just like the functions you’ve been learning about. The difference is that methods belong to a named type, like a struct!

When you were building the Bullseye app, you used structs to build up the views in the app. But structs aren’t just for defining views. You can use them to model all sorts of data.

You’re actually already very familiar with some other structures. Many of the built-in Swift types we’ve been using throughout this course, are structures. Int, Double, Bool, String, Array, Dictionary: all structures. Being able to define your own will come in handy! To demonstrate, we’ll start by turning our Student tuple into a structure.

At the top of this playground page you’ll find the typealias we used to represent a Student. It’s commented out because we’re going to create a Struct with the same name.

  • To start, use the keyword struct, and then the type’s name: Student.
struct Student {
  
}

Take note of the capital S at the start of Student. It’s a Swift convention, to start all type names like that.

  • Now to turn these tuple values into properties.

Properties are just constants or variables that belong to a type. So, you define them in a similar way. Start with let or var, and follow up their names with explicit typing. We don’t expect a student’s name to change, so that should be a constant.

let name: String

But a student’s grade might change, or they might decide they need a pet iguana, so those properties should be variables.

var grade: Int
var pet: String?
  • And note we’ve made that pet property an optional String.

When you define a structure, you’re making something like a blueprint. You haven’t created any Student in particular, yet; you’ve just laid out a common way to describe all students.

You could give these properties values right here, but in this case, we want to set those properties to different values for each Student.

  • To actually create a student, start typing out Student, and hit return for autocomplete.
Student
  • Then, type an opening parenthesis, and use autocomplete again.

  • What you’re seeing is the initializer for the Student struct. Structs automatically generate an initializer like this for you.

  • Now you can set the values for those three properties via the initializer.

Student(name: "Chris", grade: 49, pet: "Mango")

What you’ve created is known as a “Student instance”, or “instance of Student”. You can store that instance in a new variable or constant, just like you’d expect:

let chris = ...

Remember that a Struct is like a blueprint, so you can make as many students as you want. I’ll make two more:

let sam = Student(name: "Sam", grade: 99, pet: nil)
let catie = Student(name: "Catie", grade: 75, pet: "Ozma")

This Student struct has things, but it doesn’t do anything yet. To fix that, we can add a method. Writing a method is just like writing a function, except you do it inside of a type definition. I’ll write a method to find out if a student is passing, just like the function from earlier in this part.

func getPassStatus(

Because you’re inside the Student definition, you have access to its properties. That means you don’t need to pass in the grade property to use it!

You just need the lowestPass parameter this time, and you can set a default value exactly the same way you’ve done before.

func getPassStatus(lowestPass: Int = 50) -> Bool {
  grade >= lowestPass
}

I want this method to return a bool:

func getPassStatus(lowestPass: Int = 50) -> Bool {
  grade >= lowestPass
}

And inside of the method body, I’ll write the expression to compare the grade for a student to the lowest passing grade:

func getPassStatus(lowestPass: Int = 50) -> Bool {
  grade >= lowestPass
}

Remember, if the body of a function or method is only one line, the result is returned implicitly. No need to use the return keyword!

And now I can find out if a student is passing. Start with one of the constants you created followed by a dot.

chris.

Take a look at the auto-complete list and you should see all of the available properties and methods for the Student structure.

I just want to find out if Chris has passed, so I’ll choose the getPassStatus method. Because there’s a default value set for lowestPass, I have the option to call this method without arguments.

chris.getPassStatus()

This guy needs some extra credit to help that grade! I can take care of that by adding one more method that adds 10 points to the grade property.

func earnExtraCredit() {
  grade += 10
}

You should see an error at this point. When a struct’s method changes, or mutates a property of that struct, you need to explicitly say that it can do so. You can do that with the mutating keyword! Just add it right in front of func.

mutating func earnExtraCredit...

Now I can call earnExtraCredit on Chris…

chris.earnExtraCredit()

Except I can’t. The grade property is a variable, but chris is a constant. I need to change chris to a variable in order to change any of its properties.

var chris = Student...

And now earnExtraCredit can run, and if I get the pass status again… He’s passing!

chris.getPassStatus()

I mentioned in the introduction to this part that structures are really designed for representing values. A struct is what’s called a “value type”.

  • To illustrate what that means in practice, we’ll make an evil clone of one of our students. Start with a new constant:
let evilCatie
  • Then, assign the real student to that new variable
let evilCatie = catie
  • Hit the Show Result button on the right, to see that they have the exact same values for their name, grade, and pet.

  • Now, try to change the variable properties on the evil version…

evilCatie.grade = 100
evilCatie.pet = "Mustachioed Ozma"

That doesn’t work. Even though both grade and pet are variables, evilCatie isn’t. To be able to change any of the values, I need to change this let to var.

var evilCatie = catie
  • Now that those properties can change, if you show the values of both catie and evilCatie
catie
evilCatie

They no longer match!

Is that what you expected? Or in your mind, if you were to assign a Student to two different variables, would you expect them to always keep their properties in sync? Both ways of thinking are valid. But when dealing with value types, which structures are, all the variables you assign will be independent.

If you assign an instance of a structure to a constant or variable, you’re actually creating an entirely new structure, with the same values as the original.

If that makes your head spin, don’t worry. You’ll get practice with value types in the next challenge, and we’ll cover them in depth in a later course: Programming in Swift: Functions and Types.

After this next challenge, you’ll learn about classes. Classes are reference types and work a little differently. Maybe you’ll decide that Student should be a class instead of a struct, but for now, this will do.