In Swift, a closure is a special type of function without the function name. For example,
{
print("Hello World")
}
Here, we have created a closure that prints Hello World.
Before you learn about closures, make sure to know about Swift Functions.
Swift Closure Declaration
We don't use the func
keyword to create closure. Here's the syntax to declare a closure:
{ (parameters) -> returnType in
// statements
}
Here,
- parameters - any value passed to closure
- returnType - specifies the type of value returned by the closure
- in (optional) - used to separate parameters/returnType from closure body
Let's see an example,
var greet = {
print("Hello, World!")
}
Here, we have defined a closure and assigned it to the variable named greet
. Statement enclosed inside the {}
is the closure body.
To execute this closure, we need to call it. Here's how we can call the closure
// call the closure
greet()
The closure simply prints the text Hello World
.
Note: This closure doesn't have any parameters and return type.
Example: Swift Closure
// declare a closure
var greet = {
print("Hello, World!")
}
// call the closure
greet()
Output
Hello, World!
In the above example, we have defined a closure and assigned it to the variable named greet.
When we call the closure, the print()
statement inside the closure is executed.
Closure Parameters
Similar to functions, a closure can also accept parameters. For example,
// closure that accepts one parameter
let greetUser = { (name: String) in
print("Hey there, \(name).")
}
// closure call
greetUser("Delilah")
Output
Hey there, Delilah.
In the above example, we have assigned a closure to the greetUser
variable.
Inside the closure, (name: String)
specifies that the closure accepts the String
type parameter named. Notice that we have used in
to separate closure parameter with body.
Also, notice the call of closure
greetUser("Delilah")
Here, we have passed a string value "Delilah"
to our closure.
And finally, the statement inside the closure is executed.
Note: Unlike function, we call the closure without mentioning the parameter name.
Closure That Returns Value
A Swift closure may or may not return a value. If we want our closure to return some value, we need to mention it's return type and use the return statement. For example,
// closure definition
var findSquare = { (num: Int) -> (Int) in
var square = num * num
return square
}
// closure call
var result = findSquare(3)
print("Square:",result)
Output
Square: 9
In the above example, we have defined a closure that returns the square of a number. Notice the closure definition,
var findSquare = { (num: Int) -> (Int) in
...
return square
}
Here, (num: Int) -> (Int)
indicates that the closure
(num: Int)
- indicates the parameter of integer type-> (Int)
- represents the closure return value of Int typereturn square
- return statement inside the closure
The returned value is stored in the result
variable.
Closures as Function Parameter
In Swift, we can create a function that accepts closure as its parameter.
// define a function
func grabLunch(search: () -> ()) {
…
// closure call
search()
}
Here,
search
- function parameter() -> ()
- represents the type of the closuresearch()
- call closure from the inside of the function.
Now, to call this function, we need to pass a closure as its argument
// function call
grabLunch(search: {
print("Alfredo's Pizza: 2 miles away")
})
Example: Closure as function parameter
// define a function and pass closure
func grabLunch(search: ()->()) {
print("Let's go out for lunch")
// closure call
search()
}
// pass closure as a parameter
grabLunch(search: {
print("Alfredo's Pizza: 2 miles away")
})
Output
Let's go out for food Alfredo's Pizza: 2 miles away
Trailing Closure
In trailing closure, if a function accepts a closure as its last parameter,
// function definition
func grabLunch(message: String, search: ()->()) {
...
}
We can call the function by passing closure as a function body without mentioning the name of the parameter. For example,
// calling the function
grabLunch(message:"Let's go out for lunch") {
// closure body
}
Here, everything inside the {...}
is a closure body.
Example: Trailing Closure
func grabLunch(message: String, search: ()->()) {
print(message)
search()
}
// use of trailing closure
grabLunch(message:"Let's go out for lunch") {
print("Alfredo's Pizza: 2 miles away")
}
Output
Let's go out for lunch Alfredo's Pizza: 2 miles away
In the above example, the grabLunch()
function accepts a closure search: () -> ()
. Here, closure is the last parameter of the function.
Hence, we have called the function by passing the closure argument as function definition.
grabLunch(message:"Let's go out for lunch") {
print("Alfredo's Pizza: 2 miles away")
}
Autoclosure
While calling a function, we can also pass the closure without using the braces {}
.For example,
// using {}
display(greet:{
print("Hello World!")
}
// without using {}
display(greet: print("Hello World!"))
To pass the closure argument without using braces, we must use the @autoclosure
keyword in function definition. For example,
func display(greet: @autoclosure () -> ()) {
...
}
Here, the @autoclosure
automatically adds curly braces.
Example: Autoclosure
// define a function with automatic closure
func display(greet: @autoclosure () -> ()) {
greet()
}
// pass closure without {}
display(greet: print("Hello World!"))
Output
Hello World!
Note: We cannot pass arguments to an autoclosure. If we try to do so we'll get the error message as: argument type of @autoclosure parameter must be '()'
.