Photo by Zan on Unsplash

Memory management in iOS

Omer Rahmanovic
4 min readAug 20, 2022

--

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 :)

--

--