I have the following function where I have completion handler but I\'m getting this error:
Closure use of non-escaping parameter may allow it to escape
@escaping is infectious to all calling methods, and the compiler determines when you must include it.
Consider this example (which compiles):
dispatchSometime( { print("Oh yeah") })
func dispatchSometime(_ block: ()->()) {
dispatchNow(block)
}
func dispatchNow(_ block: ()->()) {
block()
}
This modified example, however, produces two errors of type non-escaping parameter may allow it to escape:
dispatchSometime( { print("Oh yeah") })
func dispatchSometime(_ block: ()->()) {
dispatchLater(block)
}
func dispatchLater(_ block: ()->()) {
DispatchQueue.main.async(execute: block)
}
The dispatch on main means the dispatchLater method needs @escaping, and once you've added that, the dispatchSometime method also requires @escaping for the example to compile.
dispatchSometime( { print("Oh yeah") })
func dispatchSometime(_ block: @escaping ()->()) {
dispatchLater(block)
}
func dispatchLater(_ block: @escaping ()->()) {
DispatchQueue.main.async(execute: block)
}
However, the take away is just:
@escaping up the call chain until the compiler stops complaining. weak with captured variables as they may be retained along with the block itself."Implications
The really fun case with this is where you have to adjust several methods to include the @escaping keyword, which gets the compiler to stop complaining. However, if those methods are actually conforming to a protocol, that protocol's methods must also get the @escaping keyword, which also infects all other protocol conformants. Fun!