When you are programming iPhone/iPad apps, the thing that tricks everyone up the most is memory management. If you are a beginner, you are likely to just not know what is going on. If you are experienced, then you find yourself battling obscure memory bugs in errant threads.
It has taken me some time to master, but I have gotten the hang of it, and it boils down to knowing just a few things. Here’s what I know about memory management on iPhone/iPad. Hopefully, this will help someone out, and if I have any errors in my thinking, someone will let me know.
Memory in Objective C
- Every time you type “retain” you also need to type “release.”
- When you type “alloc” there is an implied retain.
- When you type self.foo = bar, there is an implied retain. If you set a class variable without the “self,” there is no implied retain. EDIT: Someone on Hacker News corrected me – there is only an implied retain if you declare the property as retained in the header, with @property(retain).
- If you use a convenience method to make an object, then there is an implied “autorelease” and you don’t need a release.
Correct Examples
Each of these examples is correct. The object is properly instantiated, and then later released.
Ex. 1
NSString *foo = [[NSString alloc]init];
...
[foo release];
Ex. 2
NSString *foo = [[[NSString alloc]init]autorelease];
...
Ex. 3
self.foo = [NSString stringWithFormat:@"bar"];
...
self.foo = nil;
Incorrect Examples
All of these examples are wrong.
This example will crash, because foo is over-released:
NSString *foo = [[[NSString alloc]init]autorelease];
...
[foo release];
This will also crash and is over-released:
NSString *foo = [NSString stringWithFormat:@"bar"];
...
[foo release];
A Note on @synthesize
If you declare a class variable as a property in the header, and then synthesize it in the implementation, that will auto-generate getters and setters.
That means when you type:
self.foo = @"bar";
The following is actually happening, and you could even override this method:
- (void) setFoo:(NSString*) bar {
if(bar == foo) {
return;
}
[foo release];
foo = [bar retain];
}
EDIT: Corrected the above function based on comment on HN… shows what I know!
So, whenever you call self.foo = bar, there is both a release and then a retain.
Typing self.foo = nil releases and nils the variables.
Just typing foo = nil is a memory leak.