Memory management in iOS
When it comes to memory management in iOS apps, Swift uses Automatic Reference Counting (ARC) to track and manage your app’s memory usage. Good thing is that we developers generally do not need to worry about this because ARC automatically removes class instance references when those class instances are no longer needed. However in some cases ARC require of us more informations so it can manage memory for us.
How ARC Works
Every time we create class instance ARC allocate chunk of memory for that instance and when that instance is no longer needed ARC will free up that memory so it can be used for other purposes. To make sure that instances don’t disappear while they’re still needed, ARC tracks how many properties, constants, and variables are currently referring to each class instance. ARC will not deallocate an instance as long as at least one active reference to that instance still exists.
ARC in Action
Here we will go though practical example how ARC manages memory.
Here we created our custom class and added some properties to it then we created 2 instances of this class. Pay attention to emirates and flyDubai. Those 2 now share same address in memory and because of that both will have same property value and if you change 1 of them other will also be changed. Because of this we created strong reference in our code which means ARC will not be able to free up memory.
Strong Reference Cycles Between Class Instances
It’s possible to write code in which an instance of a class never gets to a point where it has zero strong references. This can happen if two class instances hold a strong reference to each other, such that each instance keeps the other alive. This is known as a strong reference cycle. You resolve strong reference cycles by defining some of the relationships between classes as weak or unowned references instead of as strong references.
from this example we can see that both Passenger and Airline class has strong reference to each other.
Unfortunately, linking these two instances creates a strong reference cycle between them. The Passenger
instance now has a strong reference to the Airline
instance, and the Airline
instance has a strong reference to the Passenger
instance. Therefore, when you break the strong references held by the john
and emirates
variables, the reference counts don’t drop to zero, and the instances aren’t deallocated by ARC
Swift provides two ways to resolve strong reference cycles when you work with properties of class type: weak references and unowned references.
Weak and unowned references enable one instance in a reference cycle to refer to the other instance without keeping a strong hold on it. The instances can then refer to each other without creating a strong reference cycle.
Now if we set all instances to nil deinit will be called and ARC will be able free up memory.
Unlike a weak reference, an unowned reference is expected to always have a value. As a result, marking a value as unowned doesn’t make it optional, and ARC never sets an unowned reference’s value to nil
Because there are no more strong references to the Customer
instance, it’s deallocated. After this happens, there are no more strong references to the CreditCard
instance, and it too is deallocated.
The final code snippet above shows that the deinitializers for the Customer
instance and CreditCard
instance both print their “deinitialized” messages after the john
variable is set to nil
When it comes to memory management this is only part between classes and its instances, there is also part related to closures and that one will be covered in on of the following articles. I wanted in this article to be as short as possible so you could understand in very basic example how memory is handled by ARC.
If you have any questions or suggestions feel free to comment :)