Success and Failure blocks are all over Swift code bases. They are a useful tool to do asynchronous tasks and wait for network requests. A standard signature is:
func foo(success: @escaping () -> Void, failure: @escaping () -> Void) {...}
Network Requests
func foo(success: @escaping () -> Void, failure: @escaping () -> Void) {
networkRequest.response({
success()
}).error({
failure()
})
}
In this case the function waits for the network response and then calls the success
or failure
closure. This occurs asynchronously.
Mixed Requests
func foo(success: @escaping () -> Void, failure: @escaping () -> Void) {
if (...) {
networkRequest.response({
success()
}).error({
failure()
})
}
} else {
DispatchQueue.main.async {
success()
}
}
}
The network request closure work the same, but the closure outside the network request needs to be handled differently. That closure is wrapped in a DispatchQueue.main.async
which calls it asynchronously on the main thread. Without this, some closures would be called asynchronously while others were called synchronously.
The @escaping
keyword in the function parameter specifies this and signifies that the closures are called asynchronously.
The Swift documentation describes escaping closures as "the closure is passed as an argument to the function, but is called after the function returns"