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.
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:
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
deinityourself. - A class has at most one
deinitblock. - 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
deinitinstead of Objective-C’sdealloc. - ARC calls
deinitautomatically when the last strong reference to a class instance is released. - Use
deinitfor final cleanup of external resources and observers. - If
deinitdoes not run, check for retain cycles first.

