## Capturing Values In Swift Closures

Contents

We use closures pretty much every day, and, some times, it may be not very clear what happens and how a closure works. Let’s find out how a closure captures a variable and how to prevent weird behaviours.

## Introduction

In this article, we’ll see mainly two things: how a closure captures a variable and a specific scenario where the closure captures the `self` context.

You don’t have to be a Guru of Swift closures to understand this article, but I suggest you a good understanding of what’s a strong and weak reference before starting reading this article, otherwise something may be confusing since I don’t explain thoroughly how an object reference works in Swift.

## Default Variable Capturing

When we use a closure, most of the time, we need to use variables from the surrounding context—like class properties or local variables. We are able to use these variables capturing them inside the closure. The capturing is transparent to us, we can use these variables without any efforts like in the following example:

 `````` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 `````` ``````struct Calculator { var a: Int var b: Int var sum: Int { return a + b } } let calculator = Calculator(a: 3, b: 5) let closure = { print("The result is \(calculator.sum)") } closure() // Prints "The result is 8" ``````

In this example, there is a struct `Calculator` which provides the sum of two properties. Then, we have a `Calculator` instance—`calculator`— which is captured inside `closure` to print `sum`.

Note

When we capture a variable and change its value inside the closure, we affect its value also outside the closure scope once the closure is called:

 `````` 1 2 3 4 5 6 7 8 9 10 11 `````` ``````var calculator = Calculator(a: 3, b: 5) // 0x618000220400 let closure = { calculator = Calculator(a: 33, b: 55) // 0x610000221be0 } // calculator has address 0x618000220400 closure() // calculator has address 0x610000221be0 ``````

In the example above, we instantiate a `Calculator` object which has the memory address `0x618000220400`. Then, inside the closure, we assign a new value to `calculator` and the address becomes `0x610000221be0`. Finally, after calling the closure, `calculator` remains the one set inside the closure, as we can see with the memory address.

## Capture List

Unfortunately, the implementation used in “Default Variable Capture” has a problem. If we change the value of some `calculator` properties before calling the closure, the sum inside the closure is no longer `8` but it’s the sum of the new properties values:

 ``````1 2 3 4 5 6 7 8 9 `````` ``````var calculator = Calculator(a: 3, b: 5) let closure = { print("The result is \(calculator.sum)") } calculator.b = 20 closure() // Prints "The result is 23" ``````

If we want to prevent this behaviour and print `8` even if the properties change after their capturing inside the closure, we can explicitly capture the variable with a capture list like this:

 ``````1 2 3 `````` ``````let closure = { [calculator] in print("The result is \(calculator.sum)") } ``````

In this way, we keep an immutable copy of the variable `calculator`. Thanks to this copy, further changes to `calculator`, outside the closure, will not affected the closure.

We can capture several variables in the same closure, separating them with a comma:

 ``````1 2 3 4 5 `````` ``````let closure = { [variable1, variable2, variable3] in print(variable1) print(variable2) print(variable3) } ``````

Note

Since the variables inside the capture list are immutable, they are just read-only. It means that we cannot change the value of `calculator` inside the closure:

 ``````1 2 3 4 `````` ``````let closure = { [calculator] in calculator = Calculator(a: 1, b: 2) // Throws compile error print("The result is \(calculator.sum)") } ``````

### Make Aliases

When we use a capture list, we can also use aliases to use a different name for a specific variable with the syntax `alias = variable_name`:

 ``````1 2 3 4 5 `````` ``````let closure = { [alias1 = variable1, variable2, alias3 = variable3] in print(alias1) print(variable2) print(alias3) } ``````

Therefore, we can change the closure used in the previous examples like this:

 ``````1 2 3 `````` ``````let closure = { [calc = calculator] in print("The result is \(calc.sum)") } ``````

## Capture Self Context

### Explicit `self`

If we want to capture some properties or methods of the object where we set the closure, like in the following example:

 `````` 1 2 3 4 5 6 7 8 9 10 11 `````` ``````class MyClass { var p = 0 func method() { let closure = { print("P is \(p)") } closure() } } ``````

we have the following compile error: `Reference to property 'p' in closure requires explicit 'self.' to make capture semantics explicit`.

This means that, when we want to capture some properties or methods in the `self` context, we must add explicitly `self` to tell the compiler that the variable comes from the object `self``MyClass` in our example.

We can fix the compile error like this:

 `````` 1 2 3 4 5 6 7 8 9 10 11 `````` ``````class MyClass { var p = 0 func method() { let closure = { print("P is \(self.p)") } closure() } } ``````

### Strong Reference Cycles

A strong reference cycle occurs when two objects keep a strong reference of each other. Because of this cycle, the two objects won’t be deallocated, since their reference count doesn’t drop to zero.

Let’s see an example:

 `````` 1 2 3 4 5 6 7 8 9 10 11 12 13 `````` ``````class ClassA { var refB: ClassB? } class ClassB { var refA: ClassA? } let classA = ClassA() let classB = ClassB() classA.refB = classB classB.refA = classA ``````

This is a very plain example where we can see that both `classA` and `classB` are keeping a strong reference of each other creating a strong reference cycle.

This is just a plan example and the cycle is very easy to catch. It may become more difficult when we capture `self` inside a closure, if we don’t understand well how the closure works.

By default, a closure keeps a strong reference of the variable captured. This means that in the following example:

 `````` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 `````` ``````class MyClass { func doSomethig() { } } class Handler { var closure: (() -> Void)? func setupClosure() { let obj = MyClass() closure = { obj.doSomethig() } } } let handler = Handler() handler.setupClosure() ``````

`obj` won’t be deallocated at the end of `setupClosure` scope since `closure` is keeping a strong reference of it. It will be deallocated once we destroy `closure`.

It means that if we capture `self` inside a closure—for example to use a property or a method—we keep a strong reference of `self`.

Let’s see an example where we use `self` inside a closure creating a strong reference cycle:

 `````` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 `````` ``````class MyClass { func doSomethig() { } } class Handler { var closure: (() -> Void)? let obj = MyClass() func setupClosure() { closure = { self.obj.doSomethig() } } } let handler = Handler() handler.setupClosure() ``````

In this example, `handler` keeps a strong reference of its properties `closure` and `obj`. Then, in `setupClosure`, `closure` keeps an additional strong reference of `self` to use its `obj` property. In this way, we are creating a strong reference cycle, since `closure` and `self` are keeping a strong reference of each other.

We can break this strong reference cycle using `self` in the capture list with either a weak or an unowned reference:

Weak

A weak reference is a reference that does not keep a strong hold on the instance it refers to, and so does not stop ARC from disposing of the referenced instance. This behaviors prevents the reference from becoming part of a strong reference cycle.

Apple ARC Documentation

Since a weak reference may be `nil`, the variable captured becomes an optional. Therefore, we should use a `guard` to safety unwrapped it:

 ``````1 2 3 4 `````` ``````closure = { [weak self] in guard let strongSelf = self else { return } strongSelf.obj.doSomethig() } ``````

Unowned

Like a weak reference, an unowned reference does not keep a strong hold on the instance it refers to. Unlike a weak reference, however, an unowned reference is used when the other instance has the same lifetime or a longer lifetime.

Apple ARC Documentation

This means that we should use `unowned` just when we are sure that the reference will never be `nil` inside the closure, otherwise the app would crash.

We can use an `unowned` reference like this:

 ``````1 2 3 `````` ``````closure = { [unowned self] in self.obj.doSomethig() } ``````

We don’t need the `guard` like for `weak` since an unowned reference is not optional since it cannot be nil.

Note

1. We can use `weak` and `unowned` with any variable in the capture list and we can also combine with the aliases:

 ``````1 2 3 4 5 `````` ``````let obj = MyClass() let closure = { [unowned aliasObj = obj] in aliasObj.doSomethig() } ``````

``

2. We don’t need to use `weak`/`unowned` every time we use `self`. There are situation where we don’t need it—like with the `UIView` animation method:

 ``````1 2 3 `````` `````` UIView.animate(withDuration: 5, animations: { self.obj.doSomethig() }) ``````

``

Since we are using a static `UIView` method and `self` doesn’t keep any strong reference of `UIView`.

## Conclusion

The closure is a very powerful Swift feature which allows us to read a clean and readable Swifty codebase. Moreover, we have to use closures in a lot of Apple API—like in `Foundation`, `UIKit` and so on. To take advantage of closures we must be able to master it before to hurt ourself. For this reason, with a good understanding of how a closure captures the variables, we may be able to avoid troubles like strong reference cycles.