[unowned self] in Swift: When is it needed and when is it dangerous?

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

The eternal dilemma: to use [unowned self] or not?

\n\n

If you've ever written in Swift and encountered closures, you've probably asked yourself: "Do I need to write [unowned self] inside every closure where I use self?"

\n\n

This is one of the most popular questions on Stack Overflow (tens of thousands of views), and for good reason. In 2025, with the arrival of new Swift features (such as an improved lifecycle analyzer and stricter compiler checks), the answer has become even more nuanced.

\n\n

In this article, we won't just give a dry "yes" or "no" answer. We'll break down how memory management in Swift actually works, when [unowned self] is a lifesaver, and when it's a ticking time bomb, and what best practices to use in modern projects.

\n\n

Let's go! 🚀

\n\n

A quick overview of ARC and retain cycles (for beginners)

\n\n

Before talking about [unowned self], let's recall how Automatic Reference Counting (ARC) works.

\n\n

ARC is a reference counting mechanism. Every object in Swift (a class instance) has a reference count. When you create a new reference to an object (for example, assign it to a property or put it in an array), the count increases. When the reference disappears, it decreases. When the count reaches zero, the object is deallocated.

\n\n

A problem arises when two objects reference each other (a cyclic reference). Imagine:

\n\n
class Parent {\n    var child: Child?\n}\n\nclass Child {\n    var parent: Parent? // Strong reference back to Parent\n}
\n\n

If you create a Parent and Child pair and set both references, they will hold each other forever. ARC will never zero out their counts. This is called a retain cycle.

\n\n

Closures are also reference types. When a closure captures self (for example, to call a method), it stores a strong reference to the object. If the object, in turn, stores a strong reference to the closure (for example, as a property), the same cycle occurs.

\n\n

Weak vs Unowned: What's the difference?

\n\n

To break the cycle, we use weak or unowned.

\n\n

weak self

\n
    \n
  • Always optional (self?).
  • \n
  • The reference does not increase the ARC count.
  • \n
  • When the object is deallocated, the weak reference automatically becomes nil.
  • \n
  • Safe — you always check with guard let self = self else { return }.
  • \n
\n\n

unowned self

\n
    \n
  • Not optional (self without a question mark).
  • \n
  • The reference does not increase the ARC count.
  • \n
  • When the object is deallocated, the unowned reference does not become nil. It becomes a dangling pointer.
  • \n
  • Accessing such a reference after the object is deallocated causes a crash (EXC_BAD_ACCESS).
  • \n
\n\n

The key point: unowned is a promise to the compiler: "I guarantee that the object will be alive while this closure executes." If you are wrong, the app will crash.

\n\n

When to use [unowned self] (and when not to)

\n\n

Let's break down real-world scenarios from iOS development practice in 2025.

\n\n

Case 1: [unowned self] is okay (and even preferred)

\n\n

Use [unowned self] when you are absolutely certain that self will be alive at the time the closure executes. A typical example is a closure that executes synchronously inside an object's method, and the object is guaranteed not to be deallocated before the closure completes.

\n\n
class DataFetcher {\n    var data: Data?\n    \n    func fetchData() {\n        // This closure executes synchronously inside the method\n        let processCl                

Blogs

Book Recommendations