I’m just beginning to have a look at Objective-C and Cocoa with a view to playing with the iPhone SDK. I’m reasonably comfortable with C’s malloc and free concept, but Cocoa’s references counting scheme has me rather confused. I’m told it’s very elegant once you understand it, but I’m just not over the hump yet.
How do release, retain and autorelease work and what are the conventions about their use?
(Or failing that, what did you read which helped you get it?)
Let’s start with
retainandrelease;autoreleaseis really just a special case once you understand the basic concepts.In Cocoa, each object keeps track of how many times it is being referenced (specifically, the
NSObjectbase class implements this). By callingretainon an object, you are telling it that you want to up its reference count by one. By callingrelease, you tell the object you are letting go of it, and its reference count is decremented. If, after callingrelease, the reference count is now zero, then that object’s memory is freed by the system.The basic way this differs from
mallocandfreeis that any given object doesn’t need to worry about other parts of the system crashing because you’ve freed memory they were using. Assuming everyone is playing along and retaining/releasing according to the rules, when one piece of code retains and then releases the object, any other piece of code also referencing the object will be unaffected.What can sometimes be confusing is knowing the circumstances under which you should call
retainandrelease. My general rule of thumb is that if I want to hang on to an object for some length of time (if it’s a member variable in a class, for instance), then I need to make sure the object’s reference count knows about me. As described above, an object’s reference count is incremented by callingretain. By convention, it is also incremented (set to 1, really) when the object is created with an ‘init’ method. In either of these cases, it is my responsibility to callreleaseon the object when I’m done with it. If I don’t, there will be a memory leak.Example of object creation:
Now for
autorelease. Autorelease is used as a convenient (and sometimes necessary) way to tell the system to free this object up after a little while. From a plumbing perspective, whenautoreleaseis called, the current thread’sNSAutoreleasePoolis alerted of the call. TheNSAutoreleasePoolnow knows that once it gets an opportunity (after the current iteration of the event loop), it can callreleaseon the object. From our perspective as programmers, it takes care of callingreleasefor us, so we don’t have to (and in fact, we shouldn’t).What’s important to note is that (again, by convention) all object creation class methods return an autoreleased object. For example, in the following example, the variable ‘s’ has a reference count of 1, but after the event loop completes, it will be destroyed.
If you want to hang onto that string, you’d need to call
retainexplicitly, and then explicitlyreleaseit when you’re done.Consider the following (very contrived) bit of code, and you’ll see a situation where
autoreleaseis required:I realize all of this is a bit confusing – at some point, though, it will click. Here are a few references to get you going: