swift
dealloc
memory management
iOS development
ARC

dealloc in Swift

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Swift does not use Objective-C’s dealloc method, but it has the same lifecycle concept through deinit. When the last strong reference to a class instance goes away, Automatic Reference Counting, or ARC, releases the object and runs its deinitializer so you can perform final cleanup.

deinit Is Swift’s Equivalent

A deinitializer is declared with deinit inside a class. It runs automatically before the instance is removed from memory.

swift
1final class FileSession {
2    let name: String
3
4    init(name: String) {
5        self.name = name
6        print("Opened \(name)")
7    }
8
9    deinit {
10        print("Closed \(name)")
11    }
12}
13
14var session: FileSession? = FileSession(name: "report.txt")
15session = nil

Once session becomes nil and no other strong references exist, ARC calls deinit.

What deinit Is For

deinit is the right place to release resources that ARC does not manage for you automatically. Common examples include:

  • Removing notification observers.
  • Invalidating timers.
  • Closing files or sockets.
  • Stopping long-running tasks.
  • Logging object lifetime in debug builds.

ARC handles memory ownership of Swift class references, but external resources still need deliberate shutdown.

What Usually Prevents deinit From Running

If deinit never fires, the most common cause is a retain cycle. Two objects are holding strong references to each other, so ARC never sees the reference count drop to zero.

A classic example is a closure that captures self strongly:

swift
1final class Repeater {
2    var onTick: (() -> Void)?
3
4    func start() {
5        onTick = { [weak self] in
6            self?.tick()
7        }
8    }
9
10    private func tick() {
11        print("tick")
12    }
13
14    deinit {
15        print("Repeater deinitialized")
16    }
17}

Using [weak self] breaks the cycle and allows deinit to run when the instance is no longer needed.

deinit Rules Worth Remembering

A few Swift rules make deinit different from normal methods:

  • Only classes have deinitializers. Structs and enums are value types and do not define deinit.
  • You cannot call deinit yourself.
  • A class has at most one deinit block.
  • Subclass deinitializers run before superclass cleanup completes.

This makes deinit a lifecycle hook rather than a general-purpose method.

When Not To Use It

Do not treat deinit as the only place where important business logic lives. Deinitialization timing depends on object lifetime, which can be hard to reason about in asynchronous code. If something must happen at a precise moment, expose an explicit method such as stop(), close(), or invalidate() and let deinit serve as a safety net.

That pattern is especially useful for UI controllers, network clients, and services that have meaningful shutdown behavior beyond simple memory release.

In iOS code, deinit is also a good debugging signal. If a view controller should disappear and its deinitializer never runs, that is often the first practical clue that a closure, timer, delegate, or notification observer is keeping it alive. A well-placed deinit log can expose memory-lifetime bugs much faster than staring at UI behavior alone.

Common Pitfalls

One common mistake is expecting deinit to run immediately after a screen disappears. If another object still holds a strong reference, the instance stays alive and deinit will not run yet.

Another mistake is using deinit to solve retain cycles that were never broken. If the cycle remains, the deinitializer is never reached.

A third issue is forgetting that only classes participate in ARC reference counting. Value types do not have the same lifetime hooks as reference types.

Summary

  • Swift uses deinit instead of Objective-C’s dealloc.
  • ARC calls deinit automatically when the last strong reference to a class instance is released.
  • Use deinit for final cleanup of external resources and observers.
  • If deinit does not run, check for retain cycles first.

Course illustration
Course illustration

All Rights Reserved.