Objective-C
ARC
Memory Management
Custom Dealloc
iOS Development

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

objective-c
1@interface Worker : NSObject
2@property (nonatomic, strong) NSTimer *timer;
3@property (nonatomic, assign) void *buffer;
4@end
5
6@implementation Worker
7
8- (instancetype)init {
9    self = [super init];
10    if (self) {
11        _buffer = malloc(1024);
12        _timer = [NSTimer scheduledTimerWithTimeInterval:1.0
13                                                  target:self
14                                                selector:@selector(tick)
15                                                userInfo:nil
16                                                 repeats:YES];
17        [[NSNotificationCenter defaultCenter] addObserver:self
18                                                 selector:@selector(tick)
19                                                     name:@"WorkDidChange"
20                                                   object:nil];
21    }
22    return self;
23}
24
25- (void)tick {
26    NSLog(@"tick");
27}
28
29- (void)dealloc {
30    [_timer invalidate];
31    [[NSNotificationCenter defaultCenter] removeObserver:self];
32    free(_buffer);
33}
34
35@end

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.

objective-c
1- (void)dealloc {
2    [_name release];      // Wrong under ARC
3    [super dealloc];      // Wrong under ARC
4}

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 dealloc to 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 -dealloc only for cleanup ARC cannot perform on its own.
  • Never call [super dealloc] or manual release under ARC.
  • If dealloc never runs, suspect a retain cycle rather than bad cleanup code.
  • Keep dealloc short and use earlier lifecycle hooks when a clearer cleanup point exists.

Course illustration
Course illustration

All Rights Reserved.