Understanding the concept behind closures escaping and non-escaping can be very easy to understand. When a closure is passed as an argument to a function and it is invoked after the function returns, the closure is escaping. The term escape is well put because it literally means that.

func request(_ endPoint: EndPoint, then handler: @escaping (Result<Data,Error>) -> Void) {

    let task = urlSession.dataTask(with: endPoint.url) {
       data, response, error in

        if let error = error {
            handler(.failure(error))
        } else if let data = data {
            handler(.success(data))
        }
    }

    task.resume()
}

In the example above the closure handler is called after the function returns as the method request(_, then:) is asynchronous.

By default closures are marked as non-escaping for function types in immediate parameters position, but only if not wrapped in other type such as `Tuple` or as an `Optional` where they will be no longer immediate parameters. The benefits are the performance and the ability for the compiler to optimize the code where it won’t need to increase the retain count of the closure for later use. On the other hand, If the compiler knows that a closure is non-escaping, it can take care of the details related to memory management.

func requests(_ endPoint: EndPoint, then handler: (Result<Data,Error>) -> Void) {

    handler(.success(Data()))
}

Marking a closure by default as non-escaping also means that the self keyword can used without issues as the closure is invoked before the function returns. There is no need to use a weak reference to self in the closure.

Thanks for reading! ?