I program all day in C# and C++ at my day job, so Objective-C is both natural to me (because of a mostly familiar syntax) and unnatural (because of it’s many differences). In terms of memory management, Objective-C splits the difference between C# and C++. On the iPhone, Objective-C does not have a GC, but NSObject (the base class for all of your classes) supports reference counting. Of course, you could build the exact same mechanism in C++, but it’s pervasive and included in ObjC and there’s also some support in the app runtime for an autorelease concept (release will get called for you on an object at some point when the runtime has control — you are safe in the rest of your stack frame).
When I first started Habits, I didn’t really read through the entire memory management API (there were so many other APIs to read) because I have been using reference counting for a long time (old COM programmer) and the awesome leak detector included in XCode was a good enough guide to what I was doing wrong.
However, the rules are really simple, and now that I know them, I never run into memory management issues:
- Declare all of your object pointer @properties as retain unless you have a really good reason not to. Then the setter that is generated will automatically call retain when you assign. When you reassign, it knows to call release on the old value.
- In your dealloc, assign all of your @properties to nil. This has the effect of calling release on the current values if they are not already nil.
- alloc returns an object with a reference count of 1 — so you have to balance with a release.
- If you alloc, then you should try to release in that same function. To retain the value, assign it to something that retains. Exceptions are if you are a factory function that is returning a value up to be retained by the caller.
- Obviously, each retain call needs a release.
- Built-in convenience functions return objects that are autoreleased. That means you shouldn’t call release on them — the framework will call release at some point (they are registered in an autorelease pool that that is serviced when you return back to the framework). If you created the object without an alloc/init pair, you don’t need to call release unless the docs say you do (but they probably don’t)
- Check all of your work with the leak detector. Also, if you crash, you’re probably doing it wrong — I will have more to say on that soon.
I highly recommend that you read Very Simple Rules for Memory Management in Cocoa on stepwise.com. Keep in mind that the suggestions for building proper setters is handled automatically if you declare your @properties correctly.