Weak and Unowned
Weak and unowned are used to solve leaked memory and retain cycle. Let’s talk about ARC first
ARC
It stands for Automatic Reference Counting which is used to track and manage your app’s memory usages, when you create an instance of any class, it allocates a chunk of memory to store information about the instance. And it releases memory when an object reference count is equal to 0. So, the same memory can be used by other objects.
So, how the reference count of any object becomes 0? it’s simple when none of the variable pointing to that reference of that object. Well, this was a basic idea to know more about ARC click here.
Weak
First of all, weak references are always declared as optional variables as they can automatically be set to nil by ARC when its reference is deallocated.
1 |
weak var person: Person? |
When used in closures, weak reference act like optionals, So when you use them in closures you have to optional chain them.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
class Person { var name: String var society: Society? init(name: String) { self.name = name } func checkSociety() { let printName = { [weak society] in if let name = society?.name { print(name) } } printName() } deinit { print("\(name) story ends") } } |
Have you ever wondered about what is mean by [weak self] or [unowned self] in closures. It is known as CaptureList.
Well, the square brackets indicate a capture list, which is just an array, with weak self being the only object inside. Being an array, a capture list can do more than just capture weak self. You can capture as many things as you’d like:
1 2 3 4 5 |
let printName = { [weak society, unowned self] in if let name = society?.name { print("\(self.name) lives in \(name) scoiety") } } |
Unowned
Unlike with weak references, a reference is not turned into an optional while using unowned, Still, both unowned and weak don’t create a strong reference.
Quoted from the Apple documentation:
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 initialization.
In general, be very careful when using unowned. It could be that you’re accessing an instance that is no longer there, causing a crash. The only benefit of using unowned over weak is that you don’t have to deal with optionals. Therefore, using weak is always safer in those scenarios.
1 2 3 4 5 6 7 8 9 10 11 |
class Society { unowned let person: Person var name: String init(name: String, person: Person) { self.name = name self.person = person } deinit { print("Scoiety destroyed") } } |
Why don’t we need this with value types?
In swift, we have value types and reference types, This already makes it a bit more clear, as with a reference type you actually have a reference to take care of. This means that you need to manage this relation as strong, weak, or unowned. Value types instead keep a unique copy of its data. This means that there’s no need to use a weak reference in multi-threaded environments as thee’s no reference, but a unique copy we’re working with.
Are weak and unowned only used with self inside closures?
No, We can indicate any property or variable declaration weak or unowned as long as it’s a reference type.