Friday 31 July 2009

Retain and Release rules in Objective-C

I've seen lots of people asking questions about how to manage memory properly in Objective-C so I thought I'd list out some of the rules I follow when developing for the iPhone.

Objective-C is interesting because it introduces a few additional gotchas when compared to traditional C. In C, you write free() when you write malloc() and that's pretty much it. In Objective-C it's easy to forget things. So here are the rules I try to follow:

  • When adding a new member variable to a class, add a call to release in your dealloc method as your immediate next action.

  • When assigning to a member variable outside of init* or loadView etc. release it first. If you are assigning in a setter method, check the new value for equality first.

  • When releaseing a member variable outside of dealloc, immediately assign a new value, or nil.

  • When you type alloc for a local variable, immediately add the appropriate release or autorelease code. Prefer autorelease.

  • Move your dealloc method to immediately below your @synthesize lines. This reminds you to check your release calls and you can easily see any missing ones.

  • If you implement your own NSAutoReleasePool block, wrap it in a @try...@finally:

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    @try {
            // do stuff here
    } @finally {
            [pool release];
  • If you implement a delegate property, don't retain the delegate. See this excellent post on how to avoid retain cycles (circular references): Rules to avoid retain cycles.

1 comment:

  1. Those are good general rules. I was hoping you would have touched a little on retain as well. They say when assigning an incoming argument to anther object in a method, you should retain the argument first as a general rule in case it's released somewhere else, but then what if it isn't? then you have a reference count that is 1 too large.
    Any advice on this? I'm never sure when to use retain.