Behind all the coding that we are doing, you probably have noticed some of your variables with the reference of
unowned when writing your codes. What do they really mean? Does it make your variable stronger by declaring all with the reference of strong?
The usage of
unowned are actually related to the memory management in Swift called Automatic Reference Counting (ARC). Let’s slow down a little and try to understand what everything means here. So, ARC actually does automatic reference counting. In the definition of Computer Science, Reference Counting is a technique of storing number of references, pointers, or handles into a resources such as an object, block or memory, disk space or other resources. In short, ARC actually helps store references into memory and helps clean up when it is not being used.
On a side note, reference counting in this case only applies to instance of classes and not structures and enumerations as they are both value types and not reference types.
Before we go further, why is memory management such a big deal? It is indeed a big deal as memory management plays a huge role in allocating memory so that the program can perform at the request of the user and could be free for reuse when no longer needed.
But what could really happen if you exhaust the memory?
- The task will stop performing meaning you won’t be able to execute any of your task.
- The task probably will not progress but continue running and running until it hits the limit and the program crashed.
- You probably don’t want the user to use a buggy program.
What is Automatic Reference Counting (ARC)?
As mentioned in the official documentation,
Memory management “just works” in Swift, and you do not need to think about memory management yourself. ARC automatically frees up the memory used by class instances when those instances are no longer needed.
ARC also keeps track of information such as knowing the relationship between the code and because of that, ARC is able to manage the memory resource effectively.
How does ARC work?
Each time you create a class instance through
init(), ARC automatically allocates some memory to store the information. To be more specific, that chunk of memory holds the instance, together with the values of the properties. When the instance is no longer needed,
deinit() will be called and ARC will free the memory space of that instance.
With the code below, it is pretty self explanatory but I still want you to understand what the code does. This is an example of two classes with
Person instance and
Gadget instance which has an
init method where it will set the instance’s property meaning allocate whatever information into the memory. Also, with
deinit where we will see the instance being deallocated meaning memory containing the information will free up in our case.
This is an example of a class called
Person and the instance has a
name property with a type of
Person class has an
init where it will set the instance’s
name property meaning we will allocate whatever information into the memory. In the following code, there is a
deinitwhere we will see the instance being deallocated meaning memory containing the information will free up in our case. And, the
Person instance has a
gadget property of type
String and an optional
Gadget because a person may not have a gadget. And the same theory applies with the
The Difference between Strong, Weak and Unowned Reference
If you are more of visual person, the image below basically explains the requirement of using each of the reference.
Strong vs Weak vs Unowned — Quick Facts
- Usually, when a property is being created, the reference is strong unless they are declared
- With the property labelled as
weak, it will not increment the reference count
unownedreference falls in between, they are neither strong nor or type optional. Compiler will assume that object is not deallocated as the reference itself remain allocated.
Let’s take a look at the following example. We have a variable of
Person type with the reference of “Kelvin” and a variable of
Gadget type with the reference of “iPhone 8 Plus”.
Now if you set both variables to
nil and run the code in Playgrounds like this:
Take a look at the console message. You should see both variables are deinitialized properly.
Now add the following code to assign
kelvin with an
iphone and set the
owner of the
iphone. Make sure you insert the code before setting
This is an example of how a strong reference will look like when we link the two instances together. Remember that in the
Person class that there is an additional variable of
gadget, here we are giving it a value of
iphone variable. Visually looking, this is what your code actually looks like.
Okay, run the code again in Playgrounds. You should notice that the console only shows you messages related to initialization.
Obviously, when we break the strong reference, the reference count did not drop to zero and the instances were not deallocated by ARC. Why? Let me illustrate the issue visually. The strong reference between the
Person instance and the
Gadget instance remain and cannot be broken even both
iphone were set to
This is what we call strong reference cycle, leading to memory leaks in your apps. To break the strong reference cycle and prevent memory leaks, you will need to use
Weak reference are always declared as optional types because the value of the variable can be set to
nil. In order to indicate a reference as weak, you simply add
weak keyword before the property or variable declaration like this:
ARC automatically sets weak reference to
nil when the instance is deallocated. And because of the change of value, we know that variable will need to be used here as constants will not let you change the value.
We can break the strong reference cycle by using weak references. A weak reference does not keep a strong hold on the instance. With the weak reference, we can resolve the memory leak issue as illustrated in the previous section. We will modify the
Gadget class and declare
owner as weak reference like this:
Now re-run the code in Playgrounds and see what will happen.
As you notice the console message, both variables are now deallocated properly. After changing the
owner variable to
weak, the relationship between two instances looks a little different from the previous one:
weak reference, when you set
nil, the variable can be deallocated properly because there is no more strong reference pointing to the
An unowned reference is very similar to a weak reference that it can be used to resolve the strong reference cycle. The big difference is that an unowned reference always have a value. ARC will not set unowned reference’s value to
nil. In other words, the reference is declared as non-optional types.
Use an unowned reference only when you are sure that the reference always refers to an instance that has not been deallocated. If you try to access the value of an unowned reference after that instance has been deallocated, you’ll get a runtime error.
Since an unowned reference cannot be an optional, we will modify the sample code a bit:
As you can see, the
owner variable of
Gadget is now defined as a non-optional variable and an
unowned reference. Because of this, the initializer is modified to accept the
owner as a parameter. The relationship between
Gadget is slightly difference here, if you compare it with the example of the weak reference. Here, a
Person may own a gadget but a
Gadget must have a corresponding owner.
Now let’s see how the allocation and deallocation of the instances work. Declare a variable of
Person type which is optional.
Next, create a
Person instance and assign a
Gadget instance as person’s
Here’s how the reference looks like with the two instances linked up together. The
Personinstance has a strong reference to the
Gadget instance with the
Gadget instance having an unowned reference pointed to the
Let’s try breaking the strong reference by declaring
kelvin variable to
nil and see what happens.
Run the code in Playgrounds and here is result:
As you can see, the instances of
Gadget are deallocated properly. Since we broken the strong reference of the
Person instance (i.e.
kelvin), the instance is deallocated. Consequently, as there is no strong reference to the
Gadget instance, it is deallocated automatically.
I hope you now have a better understanding of strong, weak, and unowned references. Xcode provides developers with built-in facilities to debug memory issues. For example, if you want to detect memory leaks, you can go up to the menu and select Product > Profile > Leaks. If you want us to write more about memory management and debugging tips, please leave us a comment and let us know.
About the author:
Kelvin Tan is a self taught iOS Mobile Developer who is currently active writing tutorials on his site at www.daddycoding.com. He is from Malaysia and speaks about 4 different languages. Feel free to get in touch with him if you have any questions.
The article is first published on AppCoda.com.