If you are new to Objective-C and the iPhone platform, or come from a background programming in a memory managed environment, you may have come across some memory leak issues in your application.   Hopefully this post will help you to write applications with minimal leaks.

Unlike Java which has an active garbage collector, Objective-C uses a reference counting system for memory management.  Every NSObject in Objective-C has a retainCount variable and when this count goes to zero, the object is deleted.  This means that when you create an object in Objective-C, you need to make sure that somewhere in your code that object gets released. Apple has a great guide on memory management here that goes into very good detail and is an excellent read.

The following is some pointers that are meant to augment Apple’s guide.

@property(retain)

Any attribute that has a setter method synthesized with the retain keyword will call retain on the object that is passed to it so in your classes dealloc method you need to release this object.

@interface MyClass : NSObject {


NSString * aString;

}
@property(retain) NSString * aString;

@end
//------------------------------
@implementation MyClass
@synthesize aString;


-(void)dealloc{


[aString release];  //need to call this here because of the retain keyword
[super dealloc];

}
@end

When you assign an object using this setter you need to make sure that what you assigned gets released properly.


MyClass *anObj = [[MyClass alloc] init]; //anObj has retainCount 1
NSString *myString = [[NString alloc] initWithString:@"a string"]; //myString has a retain count of 1

Incorrect:
anObj.aString = myString; //myString now has a retainCount of 2


[anObj release]; //anObj has a retainCount of 0 and gets deallocated

//however myString has a retain count of 1 (because it had 2 to begin with)

//so it is still in memory and you have a leak.

Correct:
anObj.aString = myString; //myString now has a retainCount of 2

[myString release]; //myString now has a retainCount of 1.


[anObj release];   //both anObj and myString now have retainCount of 0 and both get deallocated.

Convenince Methods

Objects created using convenience methods belong to the Autorelease pool and do not need to have release called on them.

Correct:
NSString * myString = [NSString stringWithFormat:@"a number: %i", 1];
anObj.aString = myString;

Incorrect:
NSString * myString = [NSString stringWithFormat:@"a number: %i", 1];
anObj.aString = myString;
[myString release];

Allocating member variables in init methods

If you use an accessor you must release the object that you allocated to the member variable, however if you don’t use an accessor you don’t release it.

Case 1: Using the accessor

-(id)init{


self = [super init];
if(self)
{

NSString *myString = [[NSString alloc] initWithString:@”a string”];
self.aString = myString;
[myString release];

}
return self;

}

Case 2:Directly allocating

-(id)init{

self = [super init];
if(self)
{

aString = [[NSString alloc] initWithString:@”a string”];

}
return self;

}

These are a few of the more common mistakes that people make when first writing code in Objective-C.  We hope you found this article informative.  If you have any questions feel free to ask us in the comments and we will try to get back to you promptly.