Closures (escaping and non escaping) in swift

https://swiftunboxed.com/lang/closures-escaping-noescape-swift3/

Closures

Closures in Swift are similar to that of self-contained functions organized as blocks and called anywhere like C and Objective C languages.
In Swift, functions are named closures.

Constants and variable references defined inside the functions are captured and stored in closures. Functions are considered as special cases of closures.

Closures are defined like so:

In the below case it is:

output:
Welcome to Swift Closures

The following closure accepts two parameters and returns a Bool value −

if function expressions are declared and used like so:

then closure expressions are used like this:

Function usage

Thus, functions and closures are first-class objects in Swift: you can store them, pass them as arguments to functions, and treat them as you would any other value or object. Passing in closures as completion handlers is a common pattern in many APIs we all know and love.

When you pass a closure into a function in Swift 3, there’s a new wrinkle: the compiler assumes closure parameters are non-escaping by default. What does this mean? What’s the difference between an escaping and a non-escaping closure?

Non-Escaping Closures

The lifecycle of a non-escaping closure is simple:

  • 1.Pass a closure into a function
  • 2a. The function runs the closure (or not)
  • 2b. The function returns
  • 3. When the function returns, the passed-in closure goes out of scope, thus has not escaped the function. Nothing else can reference it

closure-noescape

Notice the closure has not escaped the body of the function. When the function ends, the passed-in closure goes out of scope and there were no additional references made to the closure.

If you remember your memory management, you might say the retains and releases are balanced; the closure object’s retain count after the function returns is the same as it was before the function was called.

Escaping Closures

Inside the function, you can still run the closure (or not); the extra bit is the closure is stored some place that will outlive the function. There are several ways to have a closure escape its containing function:

  • Asynchronous execution: If you execute the closure asynchronously on a dispatch queue, the queue will hold onto the closure for you. You have no idea when the closure will be executed and there’s no guarantee it will complete before the function returns.
  • Storage: Storing the closure to a global variable, property, or any other bit of storage that lives on past the function call means the closure has also escaped.

closure-escape

References
A first class object is an entity that can be dynamically created, destroyed, passed to a function, returned as a value, and have all the rights as other variables in the programming language have. Depending on the language, this can imply: being expressible as an anonymous literal value.

When you call someMethod with the closure, note that someProperty is a property on ClassB. What happened to the requirement about always using self in closures? That requirement only applies to escaping closures and since non-escaping is the new default, you’ll have no problems running this code in Swift 3.

The closure is still capturing self but since the closure won’t live past calling someMethod, the compiler knows there’s no retain cycle risk: there’s no chance that closure parameter will make it out.

On the other hand, what if the method declaration looked like this:

Now it’s a different story. Who knows what the method will do with the closure: store it, queue it somewhere? When you call this method and provide a closure that references a property, you must explicitly write self inside the closure body to remind yourself about the capture.

Capturing as weak

Retain cycles, weak, unowned in Swift

Note that closure parameters are non-escaping by default. However, closures still strong outside properties. Hence, you’ll need to do a weak self:

The Least You Need to Know, and other examples

https://stackoverflow.com/questions/39433221/why-do-closures-require-an-explicit-self-when-theyre-all-non-escaping-by-defa

In Swift 3, closure parameters are non-escaping by default; you can use the new @escaping attribute if this isn’t what you want. Non-escaping closures passed in as arguments are guaranteed to not stick around once the function returns.

in Swift 3, only closure function arguments are non-escaping by default (as per SE-0103). For example:

As closure in the above example is non-escaping, it is prohibited from being stored or captured, thus limiting its lifetime to the lifetime of the function foo(_:).
This therefore means that any closure parameters it captures are guaranteed to not remain captured after the function exits – meaning that you don’t need to worry about problems that can occur with capturing, such as retain cycles.

However, a closure stored property (such as bar in the above example) is by definition escaping (it would be nonsensical to mark it with @noescape) as its lifetime not limited to a given function. It (and therefore all its captured variables) will remain in memory as long as the given instance remains in memory. This can therefore easily lead to problems such as retain cycles, which is why you need to use an explicit self in order to make the capturing semantics explicit.

Let’s say we have this code:

In this example code, it will create a retain cycle upon viewDidLoad() being called, as someClosure strongly captures self, and self strongly references someClosure, as it’s a stored property.