With Automatic Reference Counting (ARC) coming out soon, you could argue this post is coming almost too late. But there’s a lot of confusion over this, and I don’t think ARC will help much if you don’t understand the why of memory management.
After a couple years, I’ve come to adopt some very simple rules for memory management.
Concepts
The first step is to pick up a few concepts that will help you as you code.
- Be lazy in memory management. Rely on the compiler to do everything it possibly can. The compiler can synthesize property setters that handle memory management according to the rules you set. Rely on this.
- Ownership. Think in terms of ownership, rather than reference counting. Thinking in terms of ownership makes problems and solutions obvious. Thinking in terms of ownership will help you keep in mind the why of what you’re doing, rather than the what. After you’ve got a good grasp of why, the what becomes obvious.
- Protect your objects. Own any object that you want to keep around as long as
selfis around. - Avoid circular references. Never own an object that could own
self. This means never owningself’s delegate or data source.
Practical guidelines
But how does this translate to code? There’s a few specific and concrete things you can do to make this easier on yourself:
- Use properties to centralize memory management rules. Use
@propertyto establish the rules for memory management of an instance variable. (And@synthesizeyour properties to underscored instance variables to prevent naming conflicts.) - Pick the right memory management rule. Use
retainproperties as your default. Data sources, delegates or other objects that might own the object you’re working in should beassignproperties instead ofretain. - Rely on the centralized memory management rules. Use property set notation (
self.foo = nil;) or the property setter ([self setFoo: nil];) everywhere you change the property’s value except in the property’s setter (if you need one) In this way, you rely on theretainorassignin your@propertyto specify the memory management. If you need to useretain,releaseorautoreleaseoutside of a setter you’re doing too much. (And, also, you’ll have more work to do to be compatible with ARC.) - Avoid being called once deallocated. In
dealloc,nilany delegates you’ve set toself. (This eliminates the possibility that the object will survive longer thanselfand try to send messages toself.) - Protect your private bits, too. Don’t use raw instance variables in objects requiring memory management. Use anonymous properties.
- Containers own their contents. You not only don’t need to but must not try to manage memory in a system container. An
NSArraywill send aretainto objects that are added to it, and areleaseto objects as they are removed. If you try to manuallyretainandreleaseobjects, you’ll miss a case. - Verify. Analyze your code frequently. And profile your code early and often for leaks.