Clearing the delegate when dealloc-ing

September 25th, 2011

Often when creating a delegate relationship between two objects: A (delegate) and B (delegating object), you can sometimes run into the scenario where the delegating object outlives the delegate. Meaning that if we don't inform B that A is dealloc'ed we could end up with a fatal app crash. To flesh this idea out consider the below (contrived) example:

//some code here inside A

self.b = [[[B alloc] init] autorelease];
self.b.delegate = self;

//some code here

Now C comes along retains B (some time passes) and your app decides that it no longer needs its retain on so it releases A and B however because C has retained B, B now has a retain count of 1 where as A has zero and is dealloc'ed. Some more time passes now C calls a method on B that in turn calls A. However A doesn't exist but we never told B this, so B has a garbage pointer, pointing to what it thinks is A so we get that dreaded and hard to find crash.

What we should have done is in A's dealloc method, set the delegate back to nil, as messages set to nil are ignored and the app can continue.

//inside Object A
- (void) dealloc
{
    self.b.delegate = nil;
    //some more clean up
    [super dealloc];
}

What do you think? Let me know by getting in touch on Twitter - @wibosco