Closure Retention Cycle
Introduction
Welcome to Lesson 3 of Swift Memory Management. In Intro to Functional Swift, you’ve discovered the unique behavior of closures, and soon noticed that they are reference types like classes. From the previous lesson, however, you must be careful using references due to retain cycle.
Problem
- How to use
capture liststo prevent retain cycle in closures - When to use
unowned
Design Class
First, create a called, BobClass. It has two properties, bobClosure and name whose types are (() -> ())? and String.
1. class BobClass {
2. var bobClosure: (() -> ())?
3. var name: String = "Bob"
5. init() {
6. bobClosure = { print("Bob the Developer") }
7. }
9. deinit {
10. print("Bobclass gone")
11. }
12. }
Let us call the closure.
1. var bobClass: BobClass? = BobClass()
2. bobClass?.bobClosure!()
3. // "Bob the Developer"
Let us visualize the relationship.

The closure block is separate from the BobClass object. The bobClosureproperty has a reference to the closure block.
Since the BobClass object as one reference from the bobClass property, you may deallocate the object.
1. bobClass = nil
2. // "Bobclass gone"
Let us visualize.

Important: Notice the closure block has been also deallocated due to the reference count of zero.
Retain Cycle
Let us create a reference from the closure block.
1. class BobClass {
2. var bobClosure: (() -> ())?
3. var name: String = "Bob"
5. init() {
6. bobClosure = { print("\(self.name) the Developer") }
7. }
9. deinit {
10. print("Bobclass gone")
11. }
12. }
Important: The
selfrefers to the object created byBobClass.
Now, let us deallocate.
1. bobClass = nil
2. // Not deallocated
Let us visualize the relationship to see the retain cycle.

There is a retain cycle between the BobClass object and the closure block.
Solution
There are two ways.
Weak
The first way is to use a weak var. The closure should have a relationship as shown by the image below.

To achieve the result above, you must use capture lists. You will capture self as a weak reference.
1. class BobClass {
2. var bobClosure: (() -> ())?
3. var name: String = "Bob"
5. init() {
6. bobClosure = { [weak self] in
7. guard let object = self else {
8. return
9. }
11. print("\(object.name) the Developer")
12. }
13. }
14. }
However, the capture self within the closure has turned into an optional type. Let us review the rule of weak.
- A
weakreference allows the referencing object to becomingnil(this happens automatically when the referenced object is deallocated) - Based on the rule above, the referencing object/variable must be
optional
Unowned
You may capture self, as a non-optional type with unowned. Like weak, it does not increase the reference count.
1. class BobClass {
2. var bobClosure: (() -> ())?
3. var name: String = "Bob"
5. init() {
6. bobClosure = { [unowned self] in
7. print("\(self.name) the Developer")
8. }
9. }
10. }
unowned states that the closure block must have a non-nil reference to the BobClass object. If the object is deallocated, it will cause a runtime error analogous to force-unwrapping nil.

More Unowned
One example is not enough.
Design Independent Class
Create a class called Owner. It contains a property whose type is CreditCard?.
1. class Owner {
2. var creditCard: CreditCard?
3. deinit { print("Owner gone") }
4. }
Design Dependent Class
Create a class called CreditCard. It contains a non-optional property whose type is Owner.
1. class CreditCard {
2. unowned let owner: Owner
4. init(enterOwner: Owner) {
5. owner = enterOwner
6. }
8. deinit { print("Card gone") }
9. }
Create Instances
1. var bob: Owner? = Owner()
2. var myCard = CreditCard(enterOwner: bob!)
3. bob?.creditCard = myCard
Let us visualize.

Let us deallocate.
1. bob = nil
2. // "Owner Gone"
It works, since the Owner object has one reference from the bob property.
When myCard attempts to access its unowned property of owner, however, scary stuff happens.
1. myCard.owner // Run-time Error
Based on the definition of unowned, it must have a non-nil reference to the object. Since the Owner object has been deallocated, it crashes.
If
selfwill never be deallocated before the closure block, useunowned. If you try to access the value of an unowned reference after that instance has been deallocated, you’ll get a runtime error.
Source Code
5003_closure_retention_cycle.playground
Resources
Swift Retention Cycle in Closures and Delegate
Conclusion
Let us recap. Like classes, closures are reference types, so you must be aware of retain cycle. To prevent one, you use capture lists to set the reference from the closure to self as weak or unowned. Remember, when you set the reference as weak, the closure captures self as an optional type because the closure must be able to break the reference. If you use unowned, however, the object or variable must have a non-nil reference. The relationship can’t be broken as you’ve seen in the Owner and Credit card example. You may use unowned if you are certain that the referenced object will not deallocated before the referencing object. If not, it will cause a run-time error.
In the following lesson, you will learn one of the dreaded topics in closures: escaping and auotoclosures.
Note: Learn Swift with Bob is available on Udemy. If you wish to receive a discount link, you may sign up here.
