Capturing values

Closures can capture variables and constants from the surrounding context in which they are created. Closures can refer to these variables and modify them within their body, even if the original scope that defined variables no longer exists.

A closure is said to escape a function when the closure is passed as an argument to the function but is called after the function returns. One way that a closure can escape is by being stored in a variable that is defined outside the function.

The following is an example of escaping closures, in other words, completion handlers:

func sendRequest(completion: @escaping (_ response: String?, _ error: Error?) -> Void) { 
// execute some time consuming operation, if successfull {
completion("Response", nil)
//}
}

sendRequest {
(response: String?, error: Error?) in
if let result = response {
print(result)
} else if let serverError = error {
// Error
}
}

We have a function named sendRequest that has a parameter of type of closure, completion which it takes an OptionalString, and an Optional Error parameters, and does not return any value.

Suppose that we execute some asynchronous time-consuming operations in the body of the function, such as reading from a file, reading from a database, or calling a web service.

To call this function, we provide a closure as argument. Our closure has two variables in it: a variable named response of the Optional String type and an error variable of the Optional Error type. As our function does not have any return type, it does not return any value to its caller. Here comes the concept of escaping a function.

Our passed closure escapes our function as it will be called after our time-consuming asynchronous operation finishes with success and the following call happens:

completion("Response", nil) 

If a closure is going to be passed as an argument to a function and it is going to be invoked after the function returns, the closure is escaping. In other words, the closure argument escapes the function body. In Swift 3, we need to use the @escaping keyword in the function definition to tell our function users that closure can escape the function body.

In this call, we pass the response and error and call back the completion closure. Then the body of closure in the caller function is executed with passed variables. This concept is a very powerful concept that eases all asynchronous operations. It is very readable and easy to follow compared with mechanisms such as delegation and notification.