Skip to content

Instantly share code, notes, and snippets.

@atereshkov
Last active June 11, 2020 18:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save atereshkov/dee56f3803e40c7a6e7656360fe56a2a to your computer and use it in GitHub Desktop.
Save atereshkov/dee56f3803e40c7a6e7656360fe56a2a to your computer and use it in GitHub Desktop.
Escaping closures Swift (nonescaping & escaping difference in Swift)
/*
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"