Swift Memory Management: ARC Explained

KD Knowledge Diet
3 min readFeb 9, 2024

Memory management is a critical aspect of software development, and Swift has a robust system in place to handle it. Automatic Reference Counting (ARC) is the heart of Swift’s memory management, and understanding how it works is essential for creating efficient, leak-free applications. Let’s break down ARC, how it operates under the hood, and what you need to know to manage memory effectively in Swift.

What is ARC?

Automatic Reference Counting (ARC) is a compile-time feature that Swift uses to manage an application’s memory usage. Unlike garbage collection used in some other languages, which periodically cleans up unused memory, ARC releases objects as soon as they are no longer needed. It does this by keeping track of the number of ‘references’ to each object — if an object’s reference count drops to zero, ARC frees that object’s memory.

How Does ARC Work?

When you create a new instance of a class, ARC allocates a chunk of memory to store information about the instance. This memory includes the instance’s type information and its stored properties. As new references to this instance are created (like assigning it to a variable or passing it to a function), ARC increments the reference count. When these references go away (like when the variable goes out of scope), ARC decrements the reference count. If the count reaches zero, ARC frees up the memory used by that instance.

Strong, Weak, and Unowned References

Swift provides three types of references to control the ARC behavior:

1. Strong References:
This is the default reference type. A strong reference keeps an object in memory as long as there’s at least one strong reference to it. It’s how ARC keeps track of which objects are still in use.

2. Weak References:
A weak reference doesn’t increase the reference count. It allows you to refer to an object without keeping it around unnecessarily. Weak references must be optional variables because they automatically become `nil` when the object they refer to is deallocated.

3. Unowned References:
Similar to weak references, unowned references do not increase the object’s reference count. However, unlike weak references, they are non-optional and always expected to have a value. Unowned references are used when you are certain that the reference will never be `nil` during its lifetime.

Retain Cycles and Memory Leaks

One of the challenges with ARC is the possibility of creating a retain cycle, where two class instances hold strong references to each other, preventing ARC from deallocating them. This results in a memory leak, as the memory consumed by the instances is never released.

To resolve retain cycles, you can define some relationships between objects as weak or unowned. This ensures that one side of the relationship does not keep the other side alive unnecessarily.

ARC in Action

Here’s an example of how to use weak and unowned references:

class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
weak var tenant: Person?
deinit { print("Apartment \(unit) is being deinitialized") }
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil
unit4A = nil

In this code, when `john` is set to `nil`, the `Person` instance is no longer strongly referenced and is deallocated. Since `Apartment` has a weak reference to `tenant`, it doesn’t prevent the `Person` instance from being deallocated when `john` is set to `nil`. As a result, when `unit4A` is also set to `nil`, the `Apartment` instance is deallocated, preventing a memory leak.

Conclusion

ARC is a fundamental aspect of Swift that automates memory management, ensuring efficient use of resources without the overhead of manual memory management or garbage collection. By understanding strong, weak, and unowned references, developers can avoid retain cycles and memory leaks, creating robust and reliable applications. As you continue to develop in Swift, keep ARC in mind — it’s a silent partner in every line of code you write.

--

--

KD Knowledge Diet

Software Engineer, Mobile Developer living in Seoul. I hate people using difficult words. Why not using simple words? Keep It Simple Stupid!