Day 06
Day 06 êŽë š
Closures, part one
Brace yourself, because today weâre covering the first thing in Swift that many people have hard time understanding. Please keep in mind Flip Wilson's law: âyou can't expect to hit the jackpot if you don't put a few nickels in the machine.â
Today you have only five one-minute videos to watch, just to make sure you have time to watch videos twice if you need to. Once youâve completed each video you can read the optional extra section, and thereâs a short test to help make sure youâve understood what was taught.
1. Creating basic closures
1. Creating basic closures
Swift lets us use functions just like any other type such as strings and integers. This means you can create a function and assign it to a variable, call that function using that variable, and even pass that function into other functions as parameters.
Functions used in this way are called closures, and although they work like functions they are written a little differently.
Letâs start with a simple example that prints a message:
let driving = {
print("I'm driving in my car")
}
That effectively creates a function without a name, and assigns that function to driving
. You can now call driving()
as if it were a regular function, like this:
driving()
Creating basic closures - Additional
2. Accepting parameters in a closure
2. Accepting parameters in a closure
When you create closures, they donât have a name or space to write any parameters. That doesnât mean they canât accept parameters, just that they do so in a different way: they are listed inside the open braces.
To make a closure accept parameters, list them inside parentheses just after the opening brace, then write in
so that Swift knows the main body of the closure is starting.
For example, we could make a closure that accepts a place name string as its only parameter like this:
let driving = { (place: String) in
print("I'm going to \(place) in my car")
}
One of the differences between functions and closures is that you donât use parameter labels when running closures. So, to call driving()
now weâd write this:
driving("London")
Accepting parameters in a closure - Additional
3. Returning values from a closure
3. Returning values from a closure
Closures can also return values, and they are written similarly to parameters: you write them inside your closure, directly before the in
keyword.
To demonstrate this, weâre going to take our driving()
closure and make it return its value rather than print it directly. Hereâs the original:
let driving = { (place: String) in
print("I'm going to \(place) in my car")
}
We want a closure that returns a string rather than printing the message directly, so we need to use -> String
before in
, then use return
just like a normal function:
let drivingWithReturn = { (place: String) -> String in
return "I'm going to \(place) in my car"
}
We can now run that closure and print its return value:
let message = drivingWithReturn("London")
print(message)
Returning values from a closure - Additional
4. Closures as parameters
4. Closures as parameters
Because closures can be used just like strings and integers, you can pass them into functions. The syntax for this can hurt your brain at first, so weâre going to take it slow.
First, hereâs our basic driving()
closure again
let driving = {
print("I'm driving in my car")
}
If we wanted to pass that closure into a function so it can be run inside that function, we would specify the parameter type as () -> Void
. That means âaccepts no parameters, and returns Voidâ
â Swiftâs way of saying ânothingâ.
So, we can write a travel()
function that accepts different kinds of traveling actions, and prints a message before and after:
func travel(action: () -> Void) {
print("I'm getting ready to go.")
action()
print("I arrived!")
}
We can now call that using our driving
closure, like this:
travel(action: driving)
Closures as parameters - Additional
5. Trailing closure syntax
5. Trailing closure syntax
If the last parameter to a function is a closure, Swift lets you use special syntax called trailing closure syntax. Rather than pass in your closure as a parameter, you pass it directly after the function inside braces.
To demonstrate this, hereâs our travel()
function again. It accepts an action
closure so that it can be run between two print()
calls:
func travel(action: () -> Void) {
print("I'm getting ready to go.")
action()
print("I arrived!")
}
Because its last parameter is a closure, we can call travel()
using trailing closure syntax like this:
travel() {
print("I'm driving in my car")
}
In fact, because there arenât any other parameters, we can eliminate the parentheses entirely:
travel {
print("I'm driving in my car")
}
Trailing closure syntax is extremely common in Swift, so itâs worth getting used to.
Trailing closure syntax - Additional
Sometimes people ask me âwhy do you start some topics by saying they are hard â arenât you just putting people off?â
Obviously my goal is not to put you off Swift. Instead, my hope is that when you struggle with something you donât ever think to yourself âIâm not cut out for Swift.â If you find closures hard itâs not because you arenât smart enough â they are hard, so itâs just a sign your brain is working properly.
Donât despair. Sometimes fighting to learn something makes it stick in your head better â there is no learning without struggle!
You can do this.