Swift: Unit Testing for Retain Cycles and Memory Leaks

Image for post
Image for post

As you may already know, one of the biggest troubles in Swift and iOS development is retain cycles. Retain cycles are the causes of another major pain: Memory leaks. A retain cycle is caused every time 2 or more objects hold a strong reference to each other. Swift uses a mechanism called Automatic Reference Counting (ARC) in order to manage memory (allocations / deallocations etc.) . As the name suggests, in Layman’s terms ARC counts how many strong references of an object exist in memory and when the count for an object is 0, then ARC deallocates the memory it takes. Thus, when 2 or more objects hold strong references to each other, their count never becomes 0 because they retain each other in memory and as a result they are never deallocated and memory leaks are caused.

There are many ways to detect if an application or part of code may contain retain cycles that cause memory leaks. Most of them work in the runtime (Memory graph debugger, memory snapshots etc). However, we can write unit tests to ensure that a Class we have created does not contain any retain cycle that could cause an unwanted memory leak.

Retain cycles: An example.

In Swift all variables can either be strong or weak and by default variables are strong. The main difference between them is that strong variables increase the ARC memory count while weak variables do not. So let’s say that we have an object in memory that it has a count of 2, if we assign it to a strong variable, the ARC count for the object will become 3. If we assign the same object to a weak variable, the ARC count will remain 2.

Let’s see an example:

So on the code above there is a retain cycle. The reason is that car object has a strong reference to its wheels and its wheels have a strong reference to the car. This retain cycle will create a memory leak that may lead to unwanted results such as app crashes. But what if we could write a unit test that would be able to tell us if our class has a retain cycle or not? Then we would be perfectly sure that our code is safe and it will not result in memory related crashes.

Unit testing to avoid retain cycles and memory leaks

Α super simple and easy way to ensure that a class does not contain any retain cycle, is to write a unit test for this purpose.

Knowing that an object is only kept “alive” (existing in memory) for as long as there is at least one strong reference to it, which means that a weak reference to an object will be nil when the last strong reference is released, we can write a test that has 2 references to our System Under Test (aka SUT) which is our class. The one reference should be strong and the other one should be weak. So, if we deallocate the strong one, the weak must also become nil because this is exactly how the ARC mechanism works. In case the weak reference is not nil, it means that the class we test contains a retain cycle. And Voila! The unit test protected us from unsafe code and memory leaks!

The test for the Vehicle class we coded before would look like this. And it would fail as sut holds a strong reference to wheel1 and vice-versa.

In this gist there is the complete playground.

Conclusion

Unit tests have proved numerous times that can save us from major incidents in production and memory leaks make no exception. With the method we presented in this article, we can now be sure that any class we write will not create any retain cycle that will cause to a memory leak.

The Startup

Medium's largest active publication, followed by +773K people. Follow to join our community.

Petros Demetrakopoulos

Written by

💻Code-blooded, 🌏 Traveler ⌨️ Computer Science graduate, AUEB alumnus. Passionate Homebrewer🍺. Lifelong learner 📚.

The Startup

Medium's largest active publication, followed by +773K people. Follow to join our community.

Petros Demetrakopoulos

Written by

💻Code-blooded, 🌏 Traveler ⌨️ Computer Science graduate, AUEB alumnus. Passionate Homebrewer🍺. Lifelong learner 📚.

The Startup

Medium's largest active publication, followed by +773K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store