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.

Saturday 4 July 2009

Problem with using Audio Service system sounds for playing sounds.

A lot of people are recommending using AudioServicesCreateSystemSoundID for playing short sounds on the iPhone. I think even the official SDK documentation recommends this for sounds that are just a few seconds long.

There are a couple of problems with this that you might want to consider:

  1. You cannot control the volume of the sound. As far as I can tell there is no function in the API to let you do this.
  2. When you have your phone set to vibrate, the sounds will not play, even when headphones are plugged in. This is in contrast to using AVAudioPlayer and the like which will play sounds through the headphones in vibrate mode.

So I guess using the AudioServicesCreateSystemSoundID approach only really applies for 'alert' sounds or sounds that are not crucial to your app.

Friday 3 July 2009

Thunderfly in my LCD

It was an interesting moment when I went to squash the Thunderfly on my LCD, only to find that the little critter was BEHIND the display. Now the curse-ed thing has gone and died right in the middle of it and won't budge.

A google search shows I'm not alone with this problem, but there isn't much I can do. I don't want to take the display apart because I don't even know if I can access the corpse, and tapping the screen isn't helping.

Even worse, now there's one inside my laptop's display too. Apparently they are attracted by the light so I've turned on a lamp on my desk to try and keep them away.