Memory Management!
History:
Manual Retain Release (MRR): In the past developers would determine that an object would be kept in memory by claiming ownership on the objects that they created and relinquish it when the object was no longer needed. MRR had a reference counting system, where each object had a counter and would cease to exist when its counter went down to zero.
Present: Swift uses ARC (Automatic Reference Counting), to free developers from counting manually. Developers define variables as weak or strong. Weak variables do not add to the counter and the object declaring it does not get to retain it, strong variables do the opposite.
Inner Workings:
Whenever you create a new instance of a class, ARC sets aside memory to store information about that particular instance. Whenever you no longer need that instance ARC frees up memory and ensures that it doesn’t take up any unnecessary space. Thus, whenever you’re writing code and you assign a class instance to a property, constant, or variable they make strong references to the instance. Strong references, have a firm grip on the instance and do not allow for deallocation as long as that strong reference remains.
RETAIN CYCLES && CIRCULAR DEPENDENCY:
When we have a situation in which the ARC fails and a memory leak occurs we end up with a retain cycle. This occurs when two objects have strong references to each other and cannot be released and have their memory freed. This affects us as developers because retain cycles can be dangerous, due to high memory consumption, bad performance and crashes.
This is an example of ARC working correctly. When we run this code in a command line application we can see that the reference count is down to zero. Let’s go over what is happening, we have two objects, sejan and angela that we instantiated which each have a reference count of 1. Then we set both objects equal to nil and we can see that the objects sejan and angela have been released from memory being printed.
However, what happens when we add in another line of code stating that Angela’s best friend is Sejan? Now we have an issue of circular dependency! Circular dependency is occurring because our two objects are tightly coupled. Wikipedia states that, circular dependencies may also cause memory leaks by preventing certain very primitive automatic garbage collectors (those that use reference counting) from deallocating unused objects.
So now that we set the objects sejan and angela to nil, both of the objects that these variables were pointing to get their reference count decreased by 1. So recapping initially both objects had a reference count of two, the instantiation and referring to each other, then we set the objects to nil, thus decreasing their count by 1, but they still have a reference count of 1 each even though there are no remaining objects that reference them.
We have now created a retain cycle that prevented the objects from getting released!!! If this kept happening with other objects in your program, or if our program ran for a long time it would result in a memory leak. Memory Leak is a type of resource leak that happens due to incorrect memory allocation because memory that is no longer needed is not released. In OOP, memory leaks can happen when an object is stored in memory, but cannot be accessed by the code that’s running.
SOLUTION 1: weak variables. Strong reference increase the reference count for an object, weak references do not. Weak variables state that if there aren’t other references to this object, do not keep the object around because of this reference. Declaring a reference as weak means that we are fine with that object disappearing, but it also means that weak references must always be declared as optionals! This is because if the weak reference points to something that disappears, the weak references changes to nil. Our circular dependency no longer prevents the objects from being released.
If you want to declare a reference to an object without increasing the reference count for that object, but you don’t want that object to ever be nil once it is assigned, you can create an unowned reference instead of a weak one.