@escaping in Swift

Ahmet Giray Uçar
4 min readMar 13, 2023

--

By default, closures are non-escaping. That means the compiler will execute the current line immediately and deallocate it from the memory.

But sometimes we need to escape from this condition when using asynchronous and time taking tasks. Let’s take a look at what is the escaping keyword and how to use it?

What is an @escaping Closure?

Closures are “non-escaping” by default. Therefore you don’t need to declare closure as @nonescaping but you need to declare an escaping closure with @escaping. An escaping closure is a closure that is passed as an argument to a function or method, but is not executed immediately. Instead, the closure is saved and can be executed later, even after the function or method has returned. In other words, the closure “escapes” the function or method’s scope and can be used outside of it.

Usage

You probably seen this code;

func fetchData(from url: URL, completion: @escaping (Result<DataModel, CustomError>) -> Void) {
URLSession.shared.dataTask(with: url) { data, response, error in
if let data = data, error == nil {
let decoder = JSONDecoder()
try {
let decodedData = try decoder.decode(DataModel.self, from: data)
completion(.success(decodedData))
} catch {
print("Unable to decode")
completion(.failure(DecodingError))
}
}
}.resume()
}

This function takes two parameters, first one is URL which we don’t care right now and second one is marked with @escaping wrapper. This means that the closure can be stored and executed later. We want to execute this closure after some time, when URLSession finishes it’s work.

We want our completion closure to be called after the dataTask finishes, therefore we don’t want our completion to be executed immediately. We want our closure to escape from executing immediately.

If you take a look at how Apple created URLSession, they declared completionHandler escaping as well.

More Usage

If you “Jump to Definition” of the DispatchQueue’s asyncAfter method, the functions we give in the “execute” parameter is escaping. That is how program executes the functions after 2 seconds or x seconds you define.

Important BONUS

It is great to have escaping since it allows us to execute some tasks, or store some properties after some time, this gives us lots of flexibilities but it comes with a cost of course.

When you use closures in your code, it’s important to understand how they capture references to objects, and how this can lead to memory leaks. One way that memory leaks can occur is through strong reference cycles, which can happen when closures capture references to objects that then capture references back to the closures.

In particular, when a closure captures a reference to an object and that closure “escapes” its original scope (meaning it’s used outside of that scope), it can create a strong reference cycle if the closure and the object both hold strong references to each other. This means that neither the closure nor the object can be deallocated from memory, even if they’re no longer being used, because they’re keeping each other alive.

One way to avoid this is by using “Capture Lists” in your closures. Capture Lists allow you to specify which objects a closure should capture weakly (meaning the closure won’t keep them alive), rather than strongly. For example, if you use “self” inside an escaping closure’s implementation without a [weak] capture, the closure will keep a strong reference to “self”, and “self” will keep a strong reference to the closure, creating a strong reference cycle. But if you capture “self” weakly, the closure won’t keep it alive, and the strong reference cycle won’t be created.

It’s worth noting that non-escaping closures, which are executed immediately and deallocated from memory, don’t create strong reference cycles because their reference count is decreased to zero after they’re executed.

I hope you learnt something from the article. If you have any questions or suggestions, please contact me. Thank you for your time.

My Personal Website | GitHub | LinkedIn | Instagram | Twitter

--

--