Shall we always use unowned self inside closure in Swift
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
In Swift, closures can capture and store references to variables and constants from the surrounding context in which they are defined. This feature is incredibly powerful but can lead to a common problem called a "retain cycle," especially when working with reference types like classes. One technique to handle retain cycles is to use [unowned self] inside closures. In this article, we'll explore whether or not you should always use [unowned self] and examine some technical nuances.
Closures and Retain Cycles
Before delving into [unowned self], let's understand why retain cycles occur. Closures capture references to objects used inside them, potentially retaining those objects. If an object has a closure property that also retains the object itself, it forms a cycle, preventing deallocation and leading to memory leaks.
Here's an example:
Weak vs Unowned
There are two primary methods to break retain cycles: weak and unowned references.
- Weak References: Used when the referenced object can become nil during its lifetime. Weak references do not increment the reference count.
- Unowned References: Used when the referenced object should never be nil after it's initially set. Like weak references, they do not increment the reference count, but unlike weak references, they are non-optional.
Using [unowned self] in Closures
You might decide to use [unowned self] in closures to avoid strong references and retain cycles. With [unowned self], you assert that self will not become nil during the closure's execution.
Here's how the previous example would change:
However, using [unowned self] assumes that self will be alive when the closure is executed. If this assumption is incorrect and self is nil, your app will crash.
When to Use [unowned self]?
- Certainty: Use
[unowned self]when you are certain that the closure's lifecycle is tied toselfand cannot outlive it. - Performance: Since unowned references do not incur the overhead of optional checks, they offer slightly better performance compared to weak references.
- Memory Management: Makes more sense when you're certain the object will never outlive its reference, such as UI operations tied to a view controller's lifecycle.
When Not to Use [unowned self]?
- Uncertainty: If there's any doubt whether
selfcould be deinitialized before the closure executes, opt for[weak self]. - Different Lifecycles: When the closure and
selfmight have different lifecycles, weak references provide safety by allowingselfto be nil. - Complex or Nested Logic: If the closure contains complex operations or deeply nested logic, evaluating whether
selfstill exists becomes critical.
Practical Example
Suppose you're dealing with network requests in a view model class, and these requests should not prevent the view model from being released:
In this scenario, using [weak self] allows for safe execution even if the view model is deallocated before the request completes.
Summary Table
| Key Metric | Use [unowned self] | Use [weak self] |
| App Safety | Unsafe if self can become nil | Safe, as it handles nil gracefully |
| Performance | Slightly better due to non-optional reference | Slightly less due to optionals |
| Developer Certainty | Requires high certainty self is alive | Allows for safer assumptions on self |
| Typical Use Cases | UI updates tied to view controller lifecycle | Network calls, asynchronous tasks |
| Risk of Crashes | High if assumptions are incorrect | Low due to optional handling |
Conclusion
In conclusion, while [unowned self] can be a great tool for managing memory in Swift, its usage should be thoughtfully considered. Always evaluate the lifecycle of objects involved in your closures and choose between [unowned self] and [weak self] based on the potential risk and architecture of your code. Remember, writing safe and performant code requires leveraging the right tools in the right context.
Related reading
- Shortest path on a graph where distances change dynamically? maximum energy path
- Shortest Path to accomplish given scenario
- Shortest Sudoku Solver in Python - How does it work?
- Shortest way to check for null and assign another value if not
- Share data between two or more iPhone applications
- Shared preferences for creating one time activity
- Should a return statement be inside or outside a lock?
- Should I add async/await to a single-line function or not?

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 courseTrack 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.