Last active
June 11, 2020 18:48
-
-
Save atereshkov/dee56f3803e40c7a6e7656360fe56a2a to your computer and use it in GitHub Desktop.
Escaping closures Swift (nonescaping & escaping difference in Swift)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
A closure is said to escape a function when the closure is passed as an argument to the function, | |
but is called after the function returns. When you declare a function that takes a closure as one of its parameters, | |
you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape. | |
One way that a closure can escape is by being stored in a variable that is defined outside the function. | |
As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. | |
The function returns after it starts the operation, but the closure isn’t called until the operation is completed — the closure | |
needs to escape, to be called later. For example: | |
*/ | |
var completionHandlers: [() -> Void] = [] | |
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) { | |
completionHandlers.append(completionHandler) | |
} | |
/* | |
The someFunctionWithEscapingClosure(_:) function takes a closure as its argument and adds it to | |
an array that’s declared outside the function. If you didn’t mark the parameter of this function with @escaping, | |
you would get a compile-time error. | |
Marking a closure with @escaping means you have to refer to self explicitly within the closure. | |
For example, in the code below, the closure passed to someFunctionWithEscapingClosure(_:) is an escaping closure, | |
which means it needs to refer to self explicitly. In contrast, the closure passed to | |
someFunctionWithNonescapingClosure(_:) is a nonescaping closure, which means it can refer to self implicitly. | |
*/ | |
func someFunctionWithNonescapingClosure(closure: () -> Void) { | |
closure() | |
} | |
class SomeClass { | |
var x = 10 | |
func doSomething() { | |
someFunctionWithEscapingClosure { self.x = 100 } | |
someFunctionWithNonescapingClosure { x = 200 } | |
} | |
} | |
let instance = SomeClass() | |
instance.doSomething() | |
print(instance.x) | |
// Prints "200" | |
completionHandlers.first?() | |
print(instance.x) | |
// Prints "100" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
References:
https://docs.swift.org/swift-book/LanguageGuide/Closures.html
https://medium.com/swiftcommmunity/what-do-mean-escaping-and-nonescaping-closures-in-swift-d404d721f39d