What's a good example of an escape closure in Swift?

I'm reading the Swift programming language manual and it mentions an escaping closure. With regards to escaping closures, I don't know what they mean by "the closure is passed as an argument to the function, but is called after the function returns." Could someone provide an example on escaping closures?


An example of an escaping closure would be the completion handler in some asynchronous task, such as initiating a network request:

func performRequest(parameters: [String: String], completionHandler: @escaping (Result<Data, Error>) -> Void) {
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpBody = try! JSONEncoder().encode(parameters)

    let task = URLSession.shared.dataTask(with: request) { data, _, error in
        guard let data = data else {
            completionHandler(.failure(error!))
            return
        }
        completionHandler(.success(data))
    }
    task.resume()
}

And this is called like so:

performRequest(parameters: ["foo" : "bar"]) { result in
    switch result {
    case .failure(let error):
        print(error)

    case .success(let data):
        // now use data here
    }
}

// Note: The `completionHandler` above runs asynchronously, so we
// get here before the closure is called, so don't try to do anything
// here with `data` or `error`. Any processing of those two variables
// must be put _inside_ the closure above.

This completionHandler closure is defined as @escaping because URLSession method dataTask runs asynchronously (i.e. it returns immediately and its own closure will be called later when the request finishes).


In Swift 3 closure parameters become non-escaping by default.

We need to write @escaping closure attribute before the parameters type to indicate the closure is called after the function returns.

typealias MyOperation = (Data?) -> ()

func addToQueue(data: Data?, operation: @escaping MyOperation) {
    OperationQueue.main.addOperation {
        operation(data)
    }
}

If we remove @escaping attribute, Xcode will show the error message below

non-escaping parameter error message