Let's consider a simpler version that doesn't include any third-party libraries, extra queues, or other complexity. We'll just create a closure and immediately execute it.
func dothing(andPrint shouldPrint: Bool) {
let closure = {
guard shouldPrint else { return }
print("I printed!")
}
closure()
print("did it return?")
}
dothing(andPrint: false) // Prints "did it return?"
The return
here exits the closure, not dothing
. Since closure
could be passed to some other function, or stored in a property and executed at some later time (possibly on a different queue as in your example), there's no way for the return
to exit anything beyond itself. Consider if we were to refactor the creation of the closure into its own function:
func fetchClosure(andPrint shouldPrint: Bool) -> () -> Void {
return {
guard shouldPrint else { return }
print("I printed!")
}
}
func dothing(andPrint shouldPrint: Bool) {
let closure = fetchClosure(andPrint: shouldPrint)
closure()
print("did it return?")
}
dothing(andPrint: false) // Prints "did it return?"
It shouldn't be surprising this has the same behavior (otherwise this wouldn't be a simple refactor). Now imagine how it would (or even could) work if return
behaved any other way.
Your example is just a much more complicated version of the same thing. return
exits the closure.