With closures, there are two cases where the closure is executed before the caller is done. There is also the opposite: the calling function completes, but the closure has not been called or completed. The latter is known as an escape closure.
For all network request functions, the closure will not be called until the response is returned, so the closure waiting for the response within this type of network request function is an escape closure. Closures of this type require programmers to manually add the @escaping tag to compile.
The following code shows a non-escape closure and an escape closure. The latter has been tagged @escapings:
class AppDelegate: UIResponder, UIApplicationDelegate { var window : UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { func syncRequest(callBack: ()->Void ) { callBack() } func asyncRequest( callBack: @ escaping () - > Void) {DispatchQueue. Main. AsyncAfter (deadline: now () + 1.0, the execute: { callBack() }) } syncRequest(){ print("callback") } asyncRequest(){ print("delay 1s callback") } window = UIWindow() window! .rootViewController = UIViewController() window! .rootViewController! .view.backgroundColor = .blue window! .makeKeyAndVisible() return true } }Copy the code
Function DispatchQueue. Main. AsyncAfter used to delay. The callback is delayed for 1s to demonstrate the effect of an escape closure.
Closures may need to reference variables of the current context, so when the caller is done, if the escape closure is marked, the context of the current call remains. What happens if there is no mark in the mark place? An error is not reported at run time, but at compile time.
Because the compiler knows you didn’t call callback right away. That’s smart.
However, knowing that this is the case, I need to tag @escaping, why not just do it? I can’t answer that question yet, or do you know?