Hey friends! As it appears from the outside world, Cocoa memory management looks like a mess. It has it all:
- there’s good old malloc/free and raw C pointers
- return-by-copy almost like C++ stdlib does it
- reference counting, as in smart_ptr in C++ (but, uh, not so smart — it’s manual reference counting) and all kinds of in-house libraries
- garbage collection as in Java and pretty much all scripting languages (that was recently introduced in Mac OS 10.5)
No sweat, Apple eases the burden somewhat by giving you properties which you, uh, synthesize. That’s @property for declaration and @synthesize nameOfTheProperty in implementation (I don’t show the synthesize part for the sake of brevity).
Also, you won’t be using any of the malloc/free in Cocoa code — it’s only there for C-based APIs, and garbage collection is not available on the iphone, so I didn’t dig into it.
Like Java, Objective C has primitive types, like bool (BOOL), int or double, and object types — those that are declared as @interfaces and allocated via [[ClassName alloc] init] or acquired in some way. Primitive types you just want to assign as is:
int colorsInTheRainbow;
@property(assign) int colorsInTheRainbow;

/* will use assignment operator in the setter */
Structures like strings, dates or addresses you would probably like to copy (i.e., implement composition, in UML terms). They are called value objects in Obj-C. The way to do that is:
NSDate *paycheckDate;
@property(copy) NSDate* paycheckDate;
/* the implementation is trickier, and you'll need to release it */
Finally, for objects you want to pass by reference to modify them, or which are too heavy to copy (e.g. you would use const reference in this scenario in C++), like dynamic arrays, you use reference counting. To up the reference count on an object, call [obj retain], to release the ref use [obj release].
This poses a question of object ownership and who is responsible to release that last reference and deallocate the object. You might be thinking, if you ever did manual reference counting on objects, that anything returned to you from any function you are responsible to release. That rule normally doesn’t hold in Cocoa.
The way Cocoa returns newly created objects is by allocating and then autoreleasing them. Consider this function returning a string:
- (NSString*)employeeOfTheMonth {
return [[[employees objectAtIndex:bestEmployeeId] copy] autorelease];
}
The weirdest thing, the function ups the reference count and then says in the documentation that you shouldn’t release it. The way autorelease works is, unlike release, it doesn’t invalidate the object if the ref count is zero. It is practically a licence to leak memory. The autoreleased memory gets deallocated only when the whole autorelease pool is deallocated — worst case, on application exit (that’s practically a memory leak), but Cocoa allows you to create multiple nested pools which you can release more often, e.g. when you expect a lot of autoreleases.
The first autorelease pool is created for you by the code generator, in the main func:
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
...
[pool release];

There are probably more of them created by the framework, it is documented that one is created for every iteration of the event loop.
All so called convenience methods return autoreleased objects:
[NSString stringWithUTF8String:"In Git We Trust"]
You can use this string right away without bothering to retain it, but — if you plan to keep it over longer time (e.g. longer than the function lifespan) — then you should retain it, or else current autorelease pool could get deallocated and you’ll end up with an invalid pointer.
To sum up:
- you should release any of the retain or copy attributed properties in the dealloc method of your class. (To myself: gotta dig out why they don’t use objects for properties and release the ref in the destructor — oh, this weird Cocoa world)
- whether to retain or to copy is up to you: you’ll have to release the object either way. You’ll see Cocoa copies objects A LOT. And often you can either copy or retain.
- you don’t typically retain objects returned by convenience methods. If you need to keep it, retain it or copy it (the latter is more common I guess — since you have all those @property(copy) for value objects).
On a personal note, all this memory management extravaganza feels unnecessarily complex and error prone (remember all those iphone apps that crash — most certainly caused by invalid pointers), but as a user I also appreciate the performance of Mac OS/iphone apps over those on other platforms — who knows, maybe as ugly as it seems, Cocoa memory management model is all about the speed.
Make sure to read Cocoa Memory Management Guide for a more detailed, but not so much on the hands on side, description.