In the previous episode of Understanding Swift Memory Management, you learned how weak and unowned references can break a strong reference cycle. What sets weak and unowned references apart from strong references? What is the difference between weak and unowned references? When is it appropriate to choose an unowned reference over a weak reference? We tackle these questions in this episode.
Helping Automatic Reference Counting
I started this series by introducing you to Automatic Reference Counting. Remember that ARC helps to keep your application's memory usage in check. It does a great job, but it isn't perfect. There are times that it needs your help.
ARC can only avoid strong reference cycles if you give it a hint. It applies a set of rules to figure out when it is appropriate to deallocate an object that is no longer needed. Earlier in this series, you learned that a strong reference cycle prevents an object that is no longer needed from being deallocated. In the previous episode, we explored weak and unowned references and how they can break a strong reference cycle. By breaking a strong reference cycle, we help Automatic Reference Counting do its job.
What Is the Difference Between Strong and Weak/Unowned References?
The key difference between a strong and a weak or unowned reference is that a strong reference prevents the class instance it points to from being deallocated. That is very important to understand and remember.
ARC keeps track of the number of strong references to a class instance. This is also known as the retain count of a class instance. The class instance cannot be deallocated as long as at least one strong reference points to the class instance. That is, in a nutshell, what ARC is about.
Weak and unowned references also point to class instances. The difference is that ARC doesn't take these references into account to determine when it is safe to deallocate a class instance. In other words, weak and unowned references cannot prevent a class instance from being deallocated.
What Is the Difference Between Weak and Unowned References?
Now that we know what the difference is between a strong and a weak or unowned reference, it is time to find out what sets weak and unowned references apart. When should you choose an unowned reference over a weak reference?
What Is a Weak Reference?
In the previous episode, we discovered that the delegate
property of the UITableView
class is defined as weak. You already know why that is and why it isn't defined as strong. But why is the delegate
property of the UITableView
class defined as weak? Why isn't it defined as unowned?
A reference should be marked as weak if it is possible that the class instance the reference points to is deallocated at some point in the future. This means that a weak reference can become nil
during its lifetime. This has several consequences that are important to keep in mind.
First, ARC automatically sets a weak reference to nil
when the class instance it points to is deallocated. That is a good thing. You don't want to have a reference pointing to a class instance that no longer exists.
Second, because ARC sets a weak reference to nil
when the class instance is deallocated, weak references always need to be declared as optionals.
Third, this implies that a weak reference should always be declared as a variable. We discussed this in the previous episode.
What Is an Unowned Reference?
Unowned references differ in several aspects from weak references and they shouldn't be used interchangeably. An unowned reference is always expected to point to a class instance. That is essential to understand and remember. Because an unowned reference should always point to a class instance, it isn't necessary to declare an unowned reference as an optional. This makes unowned references more convenient than weak references, which are required to be of an optional type.
In the previous episode, we declared the account
property of the Plan
class as unowned. The account
property doesn't need to be declared as an optional. Remember that the reason for defining the account
property of the Plan
class as unowned is to avoid a strong reference cycle.
Unowned references come with a big warning, though. You are responsible for making sure an unowned reference always points to a class instance. If you attempt to access an unowned reference that no longer points to a class instance, a runtime error is thrown and your application is terminated.
Rules of Thumb
The language guide recommends using a weak reference if the class instance the reference points to has a shorter lifetime than the object that owns the reference. If you are not sure, then use a weak reference. Remember from the previous episode that the delegate
property of the UITableView
class is defined as weak.
Use an unowned reference if the reference is guaranteed to always point to a class instance. An unowned reference is an option if the class instance the reference points to has a lifetime that exceeds or is equal to that of the object that owns the reference. Remember the example from the previous episode. A plan should always have an account and an account should always have a plan. We defined the account
property as unowned to avoid a strong reference cycle.
Defensive Programming
If you are unsure if a property should be declared as weak or unowned, then default to weak. A weak reference cannot cause harm. An unowned reference can when used incorrectly. I used to use unowned references until a few years ago. I no longer use them, though. A property that is declared as unowned behaves similarly to an implicitly unwrapped optional that is defined as weak. Remember that implicitly unwrapped optionals come with a warning.
What's Next?
Even though memory management is no rocket science, it is important to understand what strong, weak, and unowned references are, what sets them apart, and when it is appropriate to use them. Memory management is a fundamental aspect of Swift and Cocoa development.