Saturday, May 29, 2010

Memory management and properties in Objective C

It is often confusing to understand memory management while using properties. Properties have semantic attributes viz. assign, copy and retain which play a vital role in memory management. Lets consider an example:
@interface MyClass : NSObject{
     NSString *myString;
     NSString *yourString;
}
@property (nonatomic, retain) NSString *myString;
@property (nonatomic, assign) NSString *yourString;
@end

In the above example you can see that both string declarations are pretty same except that myString uses retain but yourString uses assign. Now lets see how memory management works for both.

Lets see the implementation code:
@implementation MyClass
@synthesize myString;
@synthesize yourString;

-(id)init{
    if((self = [super init])){
        self.myString = [[NSString alloc] initWithString:@"this is my string"];
        self.yourString = [[NSString alloc] initWithString:@"this is your string"];
    }
    return self;
}

-(void)dealloc{
     [myString release];
     [yourString release];
     [super dealloc];
}
@end

Ok, can you see a memory leak here. See the line
self.myString = [[NSString alloc] initWithString:@"this is my string"];

Remember that we declared myString as
@property (nonatomic, retain) NSString *myString;


So using self.myString will retain the string (rather than just assign) after it has been 'alloced'. Since we must release the object when we either use alloc or retain, we have to release the object myString twice but we have released it just once in dealloc method which means we will have a memory leak.

Solutions:
Method 1:
NSString *temp =  [[NSString alloc] initWithString:@"this is my string"];
   self.myString = temp;
   [temp release];
 
Here the 'alloced' string is released right after myString retains it. myString is released in dealloc method.

Method 2:
self.myString = [[[NSString alloc] initWithString:@"this is my string"] autorelease];
Short form for method 1.

Method 3:
myString = [[NSString alloc] initWithString:@"this is my string"];
Using myString alone without the self. prefix means that we are not using it as a property. So it is not retained. Hence the string is released in dealloc method.

Now as for our another string ie 'yourString', it doesn't have any error in above sample class but lets assume if we had done something like this:
self.yourstring = [NSString stringWithString:@"this is my string"];

Remember we used assign for yourString:
@property (nonatomic, assign) NSString *yourString;

So neither did we alloc this string nor do we retain it. Hence we don't own it. Releasing this object will produce an error.

No comments:

Post a Comment