Memory Management in Objective C, Part 2
A couple days ago I talked a little bit about how the memory model works in Objective C. Today I want to expand on that a little bit, and talk about how to use the building blocks of the memory model to build your own objects that manage memory well. First I’ll talk about a few building blocks and code style issues, and then put together a full example of how this all works together.
Synthesized Properties
In case you’re unfamiliar with the way synthesized properties work, it’s worth taking a minute to talk about what they do behind the scenes. Imagine you have
NSString *words; @property(nonatomic, retain) NSString *words;
and
@synthesize words;
Now when you assign to self.words there is some work that happens behind the scenes. In practice it’s roughly the equivalent of the following:
-(void) setWords:(NSString*)newWords
{
if([newWords isEqual: words])
return;
[words release];
words = newWords;
[words retain];
}There may actually be a bit more in there, but that’s the important bit. What’s most important here is that, when you combine this with Objective C’s ability to safely send a message to any nil object, you can free your existing memory in the property by calling self.words = nil;
Naming Ivars
Most examples you see will use the same ivar and property names. I think this is a bad idea for a couple reasons.
If you have an ivar and a retain property both named words it’s very, very easy to forget to write self. when setting the property. If you forget self. then of course you set the ivar directly, which bypasses the retain/release mechanism baked into the synthesized property. A lot of PITA memory bugs trace back to this simple mistake.
It’s lame to always have to write methods with parameters like aWords or newWords when what you really mean is words. But if your ivars and properties have the same names you’ll find yourself giving bad names to parameters to avoid stepping on your ivars with your locals
So what I like to do instead is to prepend my ivars with an identifying character. So instead of an ivar words I use _words. There is some small amount of contention that developers are not supposed to do this, because Apple reserves the right to do that themselves, but I’ve never had a problem with it. If you’re really worried, then use a different prepend, like iWords or mWords to identify ivars.
Here’s an example of how I prefer to name my ivars and map them to properties:
@interface SomeClass
{
NSString *notLikeThis;
NSString *_likeThis;
}
@property(nonatomic, retain) NSString *notLikeThis;
@property(nonatomic, retain) NSString *likeThis;
@end
@implementation SomeClass
@synthesize notLikeThis;
@synthesize likeThis = _likeThis;
@endIt’s a tiny bit of extra typing but believe me, it’s going to save you a lot of heartache.
Putting It Together
With synthesized properties and well named ivars, you can now easily put together classes that handle memory without you having to think much about it, as long as you follow a couple simple rules
Always assign autoreleased objects to your retain properties: After your assignment, you want your property to hold the only count on the object. That way once the property releases the object its count will hit 0 and it will be deallocated. The best way to do this is to ensure that everything you assign to your retain properties is autoreleased.
Never put an ivar on the left side of an assign: Assigning directly to the ivar doesn’t send a release to the existing object or retain the new one. Seeing an ivar on the left of an assign should be a giant red flag
Always set your properties to nil in dealloc: By using the power of synthesized properties, setting the property to nil both sets the ivar to nil and releases whatever value is already there. If you’ve followed the other rules then this means the retain count should hit 0 and the object will be deallocated
If you follow those three rules you’ll find that memory management becomes easy (well there’s actually a fourth rule that I will cover below, but it will make more sense after an example). So without further ado, here’s an example class that manages memory in a reasonable way. This code does three things: compiles, doesn’t leak memory, and hopefully provides a useful illustration of the principles I’ve been discussing. Don’t expect it to do much more than that.
You’ll notice I don’t have calls to release all over the place, or any crazy memory drama. If you follow the simple set of rules, your memory management will just work.
The Fourth Rule
There’s one more rule that makes more sense once you’ve put everything together. You’ll notice that in my example above, delegate was an assign property rather than a retain. This is to avoid the trap of circular references leading to abandoned memory. Imagine a situation where an instance of MemoryExample is owned by some other object MemoryExampleDelegate further up the object graph. MemoryExampleDelegate has retained MemoryExample. If MemoryExample instances also retain their delegate, then there will be a circular retain as each instance retains the other. What you want is when you deallocate MemoryExampleDelegate that it nils all of its properties and they in turn are deallocated. But if the MemoryExample instance has retained MemoryExampleDelegate then that dealloc will never be called, and you’ll wind up with big chunks of objects that retain one another but are otherwise completely disconnected from the object graph. This is easily solvable by rule number four:
Retain Leaves, Assign Roots: If you imagine the object graph as a tree, then any node on the tree should be retaining its leaves, as it has an ownership stake in their existence. But it should only hold assign properties on any root nodes (delegates, parents, and the like) so that when their parents free them the dominos fall as intended, rather than leaving you with abandoned memory.
Aaaaand Scene
This is a bit of a ramble, but I hope that it’s helpful in explaining how memory works. If you have any questions let me know, and I’ll be happy to do a followup.

