Closures
Closures
Closures is a free Swift Academy lesson on CoddyKit — lesson 1 of 1. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, one of 1 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Introduction
Hello,
Closures are self-contained blocks of code. A closure is passed as a parameter to the code, or it can be used inside codes.
The closure is a type of function. It can be used by passing within the code. They are similar to lambdas in other programming languages.
memory management
One of the most important points is that Closure can store the values of constant and variables in the context it is defined.
This storage is known as closing-over.
Swift does the memory management during this storage for us.
Closure types
There are types of closures.
- Global functions are named closures. And these functions do not hold any value.
- Nested functions can carry the values of the name and the function wrapped in it.
- Closure Expression, on the other hand, is an anonymous closure and can store data from the context that surrounds itself with a simple syntax.
Closure syntax
The syntax of the closures is tried to be simplified as much as possible. The most important of these are as follows.
- Parameters in closures can be inferred.
- Return values can be inferred.
- Closed return can be made in one line.
- Argument names can be expressed as shortcuts such as $ 0 or $ 1.
- Trailing closure syntax can be used.
Info
Closure expressions mean writing closures inline, with a focus on syntax and simplicity.
closure syntax
A closure syntax is shown in the sample code below.
{ (parameters) -> return type in
statements
}
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
//If we didn't use closures, our code structure would be as follows.
var reversedNames = names.sorted(by: backward)
closure syntax
However, with Closure, we don't need to define an unnecessarily named global named closure of this type.
It is sufficient to define a simple Closure expression in the parameter. Let's look at the example.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
print(reversedNames)
///sorted method takes closure as parameter.in keyword
It is understood from the in keyword that the body of the Closure begins.
Before starting the in keyword, the parameters received by the closure and the return type must be defined.
infer type from context
Deriving Types from Context
In the above example, the Closure expression can be understood by inferring the parameters and the return type, since the sorted method comes as a closure.
Therefore, we do not have to define them as extra.
In this example, it will be understood that since the values in the names array are Strings, the parameters received by the closure will be of the String type.
Likewise, the related closure will need a Bool type to sort, so the return type will infer as Bool.
example
This will simplify the usage below.
The arrow can also be omitted from the code by inferring the return type.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
print(reversedNames)short syntax
Using long syntax instead of short syntax is preferable to avoid confusing code readers.
The above syntax can be shortened even more.
The return value can be shortened with the closed expression by removing the return keyword.
/*
In this example, the return keyword has been extracted.
It already has single expression.
There is no need to express it as an extra with return.
*/
var names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
print(reversedNames)example
In this example, the return keyword has been omitted.
There is already a single expression, and there is no need to express it as an extra with the return.
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )name shortcut
The syntax can be shortened even more. In the above example, we stated that the closure takes two parameters. (including s1 and s2) Their types are inferred.
Now we can save the trouble of expressing these parameters with shortcuts and defining them as well.
In addition, since there is no parameter definition and return value passing, the in keyword can also be omitted.
let names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: { $0 > $1 } )
print(reversedNames)
// In this example $0 will shortcut the first parameter and $1 will shortcut the second parameter.shorten example
var names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: >)
print(reversedNames)
// Greater than operator takes two parameters and the rotation type is squat.TRAILING CLOSURE
Trailing Closure
If the parameter to be passed to a closure function is the final argument of the function and the closure expression is long, it may be more useful to write it as a Trailing Closure statement.
We can use the trailing closure as a syntax sugar. Used to increase the readability of the code.
The last parameter of most iOS methods is closure.
fınal parameter
For example, in this example, the final parameter is closure.
class Animator {
class func animate(withDuration duration: Double, animations: () -> Void) {
animations()
}
}
class MyViewController {
func start() {
// With the traditional method, we can call this fund as follows.
Animator.animate(withDuration: 1, animations: { [unowned self] in
print("red")
})
}
}
MyViewController().start()Since the above code is less legible, it can be written as follows.
Since the above code is less legible, it can be written as follows.
import Foundation
Thread.sleep(forTimeInterval: 1)
print("Background color changed to red")example
When using Trailing Closure syntax, we don't have to write an argument label.
Because closures have now become a part of the formulation call.
func someFunctionThatTakesAClosure(closure: () -> Void) {
// function body goes here
}
// Here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure(closure: {
// closure's body goes here
})
// Here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}syntax
We can actually think of the trailing closure syntax as a syntax sugar. It makes the code more readable.
/*
In the example below, animations
are expressed as closure.
*/
public class func animate(withDuration: TimeInterval, animations: () -> Void)
// In traditional usage, we need to make a call like the following.
UIView.animate(withDuration: 1, animations: { [unowned self] in
self.view.backgroundColor = UIColor.red
})
/*
In this way, both the readability of the code
increases and we avoid the use of extra brackets.
If it is as above and the last parameter of the method
is closure, Swift allows to make a call like the one below.
*/
UIView.animate(withDuration: 1) { [unowned self] in
self.view.backgroundColor = UIColor.red
}We can use the code below to test the code
We can use the code below to test the code.
func greetThenRunClosure(name: String, closure: () -> ()) {
print("Hello, \(name)!")
closure()
}
greetThenRunClosure(name: "Paul") {
print("The closure was run")
}Closure Capturing Values
Closure Capturing Values
It can hold the value of variables that enclose a closure environment. You can even change the value of these variables from within its own body and have access.
Even if it's not in the original scope in which these variables were defined.
const.
Generally, he said that he can keep this data in nested functions together with Cloresure expressions. They can store the data of the outer function.
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen())
// returns a value of 10
print(incrementByTen())
// returns a value of 20
print(incrementByTen())
// returns a value of 30cont.
If you assign a closure as a class property, it will now start holding the membranes of this instance to closure.
Therefore, a strong reference cycle will be established between closure and instance.
Particular attention should be paid to memory leaks.
warning
Closure and Functions are reference types.
@escaping
We may need this usage at many points where the closure is used asynchronously.
In early versions of swift (1 and 2), the closures in swift parameters were escaping and later became non-escaping. If we needed to pass the closure non escaping, we had to specifically specify it.
In the next versions, the closure parameters have been made non-escaping in order to gain an advantage in terms of memory usage.
Now if we want to define a closure escaping we have to bypass the @escaping keyword.
@ESCAPING Keywordu
@ESCAPING Keyword
If we want to be able to call the closures assigned to a function after the function return, we need to appear with the @escaping keyword.
The closures that are defined by default to a function are reference types, but they do not increment the reference count. Because at the moment of call, the heat of this closure ends, and we do not need to increase the reference count as extra.
However, if we need the closure we are looking for as a paramere after a function is called, we may need to express it with the @escaping keyword.
nonEscaping
First, let's see how nonEscaping closure works.
When this closure is passed as a parameter to the function, the closure is processed in the body of the function and then returns to the compiler.
And after the function returns, that is, after the execution is completed, it remains out of the closure scope and is returned to memory.
Using Escaping Closure
Using Escaping Closure
When a closure function is passed as an argument, it continues to be maintained even if the closure function returns and execution is completed.
And it takes up space in memory. Until the closure is executed. There are multiple types of escaping closures.
Congratulations
Congratulations 🎉
We have come to the end of our lesson.
See you in the next lesson 😎

Frequently asked questions
Is the “Closures” lesson free?
Yes — the full text of “Closures” is free to read here on the web, and the Swift Academy course includes 1 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Swift Academy course, upgrade to CoddyKit PRO.
What will I learn in “Closures”?
Closures You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Swift Academy?
No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 1, so you can start here or from the beginning and move at your own pace.
How long does the “Closures” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Swift Academy lesson?
Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.