If you are coming from Java, you are probably used to creating variables and having someone else clean up your mess after you are finished with them. Unfortunately, on the iPhone, you have to clean up after yourself. If you don't, your program will leak memory.
It isn't exactly manual labor, however. The NSObject class has some accounting stuff that keeps track of how many other objects are currently using the object in question ("retain count"). But unlike Java, it isn't automatic...you will have to adjust this count yourself.
The analogy that is frequently used is that of a time-share condo...a condominium with multiple owners. And this condo sits on valuable land. As soon as the all the owners are done using the condo, it can be bulldozed to make way for other buildings. The "retain count" of the condo would be the number of owners (i.e. those who are still wanting to use it).
Adjusting the Retain Count
The rule of managing memory is to make sure that, by the time the program has finished executing, the number of "ownership methods" called on an object will equal the number of "loss-of-ownership" methods.
Don't release anything you don't own. You own anything that (any of the following):
- you call [myClass alloc] explicitly on
- you explicitly [myObject retain]
- you create an object with a method that has the word "copy" in it.
To release something you own, you can either:
- call [myObject autorelease] - will release later
- call [myObject release]
Never directly call dealloc...you should always use release, and let the system decide when to deallocate.
You should override dealloc for each of your objects, and inside that method, release anything you have retained. And the end of the method, call [super dealloc]; (It's okay to call release on a null object).
When you implement a "set" method for encapsulation, you should do the following:
- (void) setSomeObject: (NSObject*) aNewObject
[aNewObject retain]; //#1
[myObject release]; //#2
#3 obviously sets the new object
#2 is called just in case you have a previous object...you should release it before you set it free. It is perfectly okay to call release on a null object.
#1 - always retain the new one first, just in case they are passing the same object in that is already assigned. Otherwise, you may end up deallocating the object.
And if you release a variable somewhere other than dealloc, you might want to set that variable to nil immediately afterwards.
Suppose you add a convenience constructor to your own object. Or you have a method that allocates and returns an object that you don't plan on "owning". If you call "alloc", you will have to balance that out with a release of some sort. But you can't call "release" before you return it--the object will cease to exist. So instead, you call "autorelease". This will cause it to be released at some point in the near future, but not immediately.
+ (id) createAnObjectForMe
return [[[MyClass alloc] init] autorelease];