Custom dealloc and ARC Objective-C
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
ARC removes most manual retain and release calls from Objective-C, but it does not eliminate cleanup work altogether. You still implement -dealloc when the object owns non-object resources or participates in registrations that must be undone before destruction.
What ARC Handles for You
Under ARC, strong Objective-C references are released automatically when the object is torn down. That means you do not write manual release calls for normal object instance variables, and you must not call [super dealloc].
So if ARC already manages object lifetimes, what remains for -dealloc? The answer is cleanup that ARC cannot infer.
Typical examples include invalidating timers, removing notification observers, closing file descriptors, freeing C buffers, or disposing of Core Foundation objects that are not automatically bridged.
That last example is easy to miss. ARC can manage bridged Objective-C objects, but raw Core Foundation ownership rules still matter when you create or retain CF objects directly.
A Correct ARC dealloc
This is a good ARC use of dealloc. It cleans up resources that are not solved simply by releasing object references.
What Not to Do
The classic manual-memory-management pattern does not apply under ARC.
ARC inserts the correct object releases automatically. Your job in dealloc is cleanup, not ownership bookkeeping.
Another common mistake is doing substantial business logic in dealloc. By the time teardown runs, object graphs may already be partially dismantled. Keep the method short, defensive, and focused on releasing external resources.
Retain Cycles Are a Different Problem
Sometimes developers reach for dealloc because an object never seems to be destroyed. That is usually not a dealloc problem at all. It is a retain cycle.
For example, a repeating timer, block, or delegate relationship may keep the object alive forever. In that case dealloc is never called, so putting more cleanup there does not fix the leak. The correct fix is to break the strong reference cycle with a weak reference or explicit invalidation earlier in the lifecycle.
Prefer Earlier Cleanup When Possible
dealloc should be the last safety net, not the primary lifecycle hook for every teardown action. If a view controller stops observing notifications in viewDidDisappear or a service closes a file in an explicit stop method, that is often clearer than waiting for destruction.
Use dealloc for cleanup that must happen before the object dies and that has no better dedicated lifecycle point.
Common Pitfalls
- Calling
[super dealloc]under ARC, which is forbidden. - Releasing Objective-C objects manually even though ARC already handles strong references.
- Using
deallocto compensate for retain cycles instead of fixing the cycle itself. - Putting complicated application logic in
dealloc, where object state may already be fragile. - Forgetting to clean up C resources, observers, timers, or other non-ARC-managed state.
Summary
- ARC manages Objective-C object references automatically, but not every external resource.
- Implement
-dealloconly for cleanup ARC cannot perform on its own. - Never call
[super dealloc]or manualreleaseunder ARC. - If
deallocnever runs, suspect a retain cycle rather than bad cleanup code. - Keep
deallocshort and use earlier lifecycle hooks when a clearer cleanup point exists.

