strong, weak, unowned – Reference Counting in Swift
original source : https://medium.com/@chris_dus/strong-weak-unowned-reference-counting-in-swift-5813fa454f30
This article explains Apple’s memory management in Swift. Even if it gets handled mostly automatic there are still some pitfalls. Choosing the correct reference type to describe the relationship between objects help you to avoid memory leaks.
Automatic Reference Counting
Apple’s implementation for automatic tracking and managing of memory usage is called ARC (Automatic Reference Counting). It automatically frees up the memory when objects aren’t referenced anymore. To know which objects are still in use it tracks the relationship between objects by increasing and decreasing a reference count. Objects can only be deallocated when the reference count is zero. ARC only applies to instances of Classes. Structs, Enums and Value-Types are not passed by reference. This is a another great reason to use Structs instead of Classes whenever possible.
Strong
You’ll find strong references almost everywhere in Swift because it’s the default declaration of a property. This doesn’t lead to a problem when you have a linear reference flow. When you deallocate the parent and decrease the retain count, all child get decreased as well. Here is an example of a strong reference:
import Foundation class Car { var brand: String init(brand: String) { self.brand = brand print("Car of the brand (brand) allocated") } deinit { print("Car of the brand (brand) is being deallocated") } } do { let tesla = Car(brand: "tesla") }
The initialisation of the car object is wrapped in a do block. This creates a scope around it. At the end of the scope the object gets deallocated and everything is fine:
Car of the brand tesla allocated
Car of the brand tesla is being deallocated
However it’s possible to write code with a strong reference cycles between class instances. This modified version of the previous example shows a reference cycle:
import Foundation class Car { var brand: String var owner: Owner? init(brand: String) { self.brand = brand print("Car of the brand (brand) allocated") } deinit { print("Car of the brand (brand) is being deallocated") } } class Owner { var name: String var car: Car? init(name: String) { self.name = name print("Owner (name) allocated") } deinit { print("Owner (name) deallocated") } } do { let tesla = Car(brand: "tesla") let misterX = Owner(name: "Mister X") tesla.owner = misterX misterX.car = tesla }
The car object now also has an optional reference to an Owner and the Owner has an optional reference to a Car. The output is:
Car of the brand tesla allocated
Owner Mister X allocated
The strong reference cycle prevents the retain count to reach zero to get deallocated and free up the memory. To solve this issue we need weak references.
Weak
Unlike strong references weak don’t increase the retain count by one. So they don’t protect the object from being deallocated by the ARC. On deallocation the weak reference will be automatically set to nil. This is the reason why all weak references are mutating optional variables. Defining a constant as weak is not possible.
Let’s take a look at the previous example. Using a weak reference between the car and owner helps to fix the deallocation:
class Car { weak var owner: Owner? ... } class Owner { weak var car: Car? ... } ...
Now ARC correctly deallocates all objects:
Car of the brand tesla allocated
Owner Mister X allocated
Owner Mister X deallocated
Car of the brand tesla is being deallocated
Note: Using only one weak reference in the Car or Owner class instead of both would have fixed the issue as well and dissolve the strong reference cycle.
Unowned
Unowned references behave similar to weak ones. They don’t increase the retain count by one as well. Unlike weak references unowned don’t have to be an Optional because they aren’t automatically set to nil on deallocation. It’s important that you only use unowned references when you really know that the object will never be nil once it has been set.
According to Apple it’s best to use when your reference and the referenced code will be deallocated at the same time.
weak vs. unowned – an advice from Apple
“Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialisation.” Apple Documentation
fin
Apple’s automatic memory management doesn’t prevent you from producing memory leaks. Non-linear strong references and reference cycles can prevent the retain count from reaching zero. The use of weak and unowned references help you to avoid this and keep your app memory in balance.