Swift
memory management
weak reference
unowned reference
programming concepts

What is the difference between a weak reference and an unowned reference?

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

When working with reference types in programming, especially in languages like Swift, understanding memory management is crucial to avoid issues like strong reference cycles. Two common types of references used for memory management are weak references and unowned references. Both are designed to help manage the lifecycle of objects without holding them strongly, but they differ in their approach and use cases.

Understanding References in Memory Management

Before delving into the differences, it's crucial to grasp the concept of memory management. In many modern programming languages, memory management is about ensuring that objects are retained in memory only as long as necessary to avoid resource waste. In Swift, this is typically handled by Automatic Reference Counting (ARC), which automatically tracks and manages the memory used by app objects.

Strong References

By default, Swift uses strong references to keep instances alive. Every time an instance of a class is created, its reference count is incremented. The instance will remain alive in memory as long as its reference count is non-zero. This can sometimes lead to situations where two or more objects reference each other in a cycle, preventing ARC from deallocating them – a scenario known as a strong reference cycle.

Weak References and Unowned References

To address strong reference cycles, Swift introduces weak references and unowned references. Both are part of the solution towards avoiding cyclic dependencies, but they are used in different scenarios.

Weak References

A weak reference is a reference that doesn't keep an object in memory. If you declare a reference as weak, it does not increment the reference count of the object it points to. This means that if the last strong reference to an object is removed, the object is deallocated, and any weak reference is set to nil.

Characteristics of Weak References:

  • Optional: Always declared as an optional type because of their ability to become nil.
  • Does Not Increase Reference Count: They don't increase the reference count of the object they reference.
  • Automatically Set to nil: Once the object a weak reference points to is deallocated, the weak reference itself is automatically set to nil.
  • Usage Scenario: Best used when one object references another and it’s possible for the latter to become nil during the lifetime of the first object. A common example is between a view and its delegate.
swift
1class Person {
2    var dog: Dog?
3}
4
5class Dog {
6    weak var owner: Person?
7}

Unowned References

An unowned reference also does not increase the reference count. However, unlike a weak reference, it’s assumed that if you access an unowned reference, the object is guaranteed to be in memory.

Characteristics of Unowned References:

  • Non-Optional: Typically declared as non-optional, as they are assumed to always have a valid value when accessed.
  • Does Not Increase Reference Count: Like weak references, they don’t increase the reference count of the object.
  • No Automatic nil: They're not automatically set to nil. If the instance they refer to is deallocated, trying to access the unowned reference results in a runtime crash.
  • Usage Scenario: Best used in scenarios where an object references another, and you know the referenced object will never be nil for the lifetime of the referencing object. Typically, it is used in parent-child relationships where one child never outlives the parent.
swift
1class CreditCard {
2    let number: String
3    unowned let customer: Customer
4    
5    init(number: String, customer: Customer) {
6        self.number = number
7        self.customer = customer
8    }
9}
10
11class Customer {
12    let name: String
13    var card: CreditCard?
14    
15    init(name: String) {
16        self.name = name
17    }
18}

Comparison Table

AttributeWeak ReferenceUnowned Reference
Memory ManagementDoes not increase reference countDoes not increase reference count
OptionalYes (always optional)No (usually non-optional)
Becomes nil on DeallocationYesNo, leads to runtime crash if accessed
Use Case ExampleDelegate patternsParent-child relationships
Suitable WhenObject can become nil at some pointObject is guaranteed to exist

Conclusion

Understanding the differences between weak and unowned references is essential for effective memory management in Swift. Weak references should be used when an object might be deallocated, and it's acceptable for the reference to become nil. Unowned references are suitable when the object reference is guaranteed to exist whenever accessed but are risky, as accessing a deallocated unowned reference results in a runtime error.

By choosing the appropriate type of reference for different scenarios, you can build more robust and efficient applications while effectively managing memory.


Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.