WEAK and UNOWNED save the day

Very well then, how do we stop these retain cycles from occurring? We certainly can’t write a whole app without object references — at least not one that does anything useful.

Enter the WEAK keyword.

An object reference created using the WEAK keyword does NOT increase the reference retain count by 1. In addition, weak references zero out the pointer to your object when it successfully deallocates.

Because a weak reference might be pointing to an object that has already been de-allocated (nil), all weak references have to be non-constant (var, not let) optionals.

WEAK in action — Delegates and their Delegatees

One very common scenario for retain cycles are Delegates.

Often times we have a controller with a child controller. The child controller creates a reference to its parent in order to notify it when certain events occur.

class ParentController: UIViewController, ChildControllerProtocol { let childController = ChildController() func viewDidLoad() {

childController.delegate = self

} } protocol ChildControllerProtocol: class {} class ChildController: UIViewController {

var delegate: ChildControllerProtocol?

}

We can clearly see how the child controller holds a strong reference to its parent — causing a retain cycle and a memory leak.

The fix for this retain cycle is a one-liner:

weak var delegate: ChildControllerProtocol?

By using the weak keyword we are now preventing a retain cycle by not increasing the delegate’s retain count by 1, and we are also telling ARC to zero-out the pointer to object once it’s de-allocated.

Using weak references to delegates is encouraged by Apple engineers, let’s take a look at the definitions for UITableViewDelegate and DataSource:

weak public var dataSource: UITableViewDataSource?

weak public var delegate: UITableViewDelegate?

Even more common: Closures

class CarClass { var valves = 5

var engineClosure : (() -> Void)? init() { engineClosure = {

print(self.valves)

}

}

} var car = CarClass()

Here we have an even more common scenario: The object holds a strong reference to the closure, and the closure holds a strong reference to the object (via self.valves)

Swift provides an elegant solution to this problem, known as a closure capture list.

Each item in a capture list is a pairing of the weak or unowned keyword with a reference to a class instance (such as self) or a variable initialized with some value. These pairings are written using the swift array syntax.

engineBlock = { [weak self] in print(self.valves) }

It is important to note that not all closures cause retain cycles, it only happens when you are holding a strong reference to the block.

The odd “UNOWNED” and its uses

More often that not, we see the list for a closure that captures “self” declared as follows:

[unowned self] in

What is unowned and why is it replacing the weak keyword?

Weak and unowned references are very similar, but their difference is very important: and unowned reference can never be an optional. Also, unowned references do not zero-out the pointer when an object is de-allocated, which may lead to dangling pointers.

For Obj-C geeks: “unowned” maps to “unsafe_unretained”.

When should we use unowned instead of weak? Quoting Apple engineers:

If the captured reference will never become nil, it should always be captured as an unowned reference, rather than a weak reference.

And:

Define a capture in a closure as an unowned reference when the closure and the instance it captures will always refer to each other, and will always be deallocated at the same time.

Summary

You have read about automatic reference counting, object referencing and retain-cycles. Although you’ll probably need a couple of projects of your own with their own retain cycles in order to master this knowledge, now you have the all the tools necessary.