- Intro to course
- Learning Objectives
- Closures
- Trailing Closures
- Capturing values
- Escaping and Non escaping
- Identify use cases of closures
- Know the difference between escaping and non escaping closures
- Implement closures as completion handlers
- Use closures to pass data between View Controllers
- Brainstorm everything you know about closures.
Self contained blocks of functionality that can be passed around and used in your code.
Basically blocks of code that we can assign to a variable, pass around in our code, then called so they can execute their code.let greeting = {
print("Welcome back!")
}
greeting()Then it gets called by calling the name of the constant with ().
let greeting:(String) -> () = { name in
print("Welcome back, \(name)!")
}
greeting("Tahoe 🐶")The keyword "in" separated the closure parameters and the body.
We can give parameters any name we want to use or leave them blank to use shorthand values.
When we call the closure, it will need a value for such parameter.
let greeting:(String) -> () = {
print("Welcome back, \($0)!")
}
greeting("Tahoe 🐶")We can send closures as parameters to functions. If the closure happens to be the last parameter sent, we can use trailing closure syntax
func washHands(action:()->()) {
print("Get some soap 🧼")
action()
print("Hands are clean. 🙌🏼")
}Can be called:
washHands() {
print("Singing for 20 seconds 🎤")
}Closures have a distinct feature that makes them stand out: they can capture values from their surrounding context.
From Apple's documentation:
A closure can capture constants and variables from the surrounding context in which it is defined. The closure can then refer to and modify the values of those constants and variables from within its body, even if the original scope that defined the constants and variables no longer exists.
Variables, functions and closures have a scope. This scope determines if we can access any of them. Simply if a variable, function or closure isn't in a scope, we can access it.let location = "San Francisco"
let explore = {
print("Exploring \(location)")
}
explore()Here's another example of closures closing over variables.
func addScore(_ points: Int) -> Int
{
let score = 42
let calculate = {
return score + points
}
return calculate()
}
let value = addScore(11)
print(value)Closures come in two different variants - escaping and non-escaping.
When a closure is escaping it means that the closure will outlive, or leave the scope that you’ve passed it to.
Non-escaping closures are called within the function it was passed into.
An example of an escaping closure is a completion handler. It’s executed in the future, after a lengthy task completes, so it outlives the function it was created in.In an escaping closure, the lifecycle looks like this:
- Passing the closure to a function as argument
- Function performs a task
- Return compiler back
- The closure runs asynchronously
By default, all closures are non escaping. This helps with memory management.
In a non escaping closure, the lifecycle looks like this:
- Passing the closure to a function as argument
- Function performs a task
- Running the closure
- Return compiler back
Download this working example and look at the code to find out how closures are being used to pass data between view controllers
Identify:
- Q: What does the app do?
- Q: Where are closures being used?

