Introduction
Let’s say we have defined a variable in a context and we are using the variable somewhere else in the context, let’s say a function. If we try to use it to function somewhere else in our code we need to refer to the variable in the context as well. However, this usually won’t be possible in a regular sense. This is where Closures come into play.
Closures basically store a reference to any constant and variable in a context in which they are defined so that they can be used anywhere they may be needed. This is known as closing over the variables and constants in question. Closures are basically blocks of code that can be defined as self-contained in the sense as they can be passed around in methods and can be executed in the method as well.
Till Swift 2, closures were escaping by default which basically means that closure can escape during the function body execution if not marked as nonescaping. However, from Swift 3 onwards it is set to nonescaping by default. In this blog, we will learn about the escaping and non-escaping closures and why the changes in the default happened.
Non-Escaping Closures
When we pass a closure as an argument in a function, the closure gets executed along with the function’s body and returns the compiler back. As soon as the execution completes the closure that we initially passed goes out of scope as well and it can not be found in the memory anymore.
The lifecycle of any nonescaping closure is as follows:
- The closure is passed as an argument during the function call.
- The function is executed as it should
- Function comes along the closure and executes
- The function completes execution and returns the compiler back
Example
func find_max(_ array:Array<Int>, performMax:((Int) -> Void)){
var max: Int = 0
//finding the max element of an array
for value in array{
if(value>max){
max=value
}
}
performMax(max)
}
// a normal function call in closure will be non-escaping as the default is non-escaping.
func calculation(){
//create an array and pass it into the function find_max.
let array = [542,45,459,12,9]
find_max(array) { (max) in
//print output
debugPrint(max)
}
}
//call the function
calculation()
//closure has no existence in memory after execution
Output
In the above example, the closure is not escaping the execution and after the print statement it will have no existence in the memory