Calvin's

Icon

designs and hacks. people and products.

Memory Management: Important Keywords

In our previous post, we discussed about memory management with reference counting in Cocoa Touch.

Here’s a summary of the keywords we use in association with our memory management tasks. Wonderful as a quick reference and as an overview!

alloc

This allocates memory for an object we are creating.  Example:

NSString *str = [ [ NSString alloc ] initWithString:@"Hello"];

Here, we are creating an NSString object and instantiating it with a default string “Hello”.  When the object is created, the reference count is 1.  We will need to release the object once we are done with it.

new

Besides using the alloc keyword to allocate memory for an object, we can also use the new keyword:

NSString *str = [ NSString new ];

The new keyword is equivalent to writing:

NSString *str = [ [ NSString alloc ] init ];

Similarly, we will need to release this object we have created once we are done with it.

retain

The retain keyword increases the reference count of an object by 1.  Consider this:

NSString *str = [ [ NSString alloc ] initWithString:@"Hello" ]
NSString *str2 = str;

In this example, we do not own str2 because we did not use the alloc keyword on the object.  When str is released, str2 will no longer be valid.  If we want to be sure that str2 is still available even if str is released, we will need to use the retain keyword like this:

NSString *str = [ [ NSString alloc ] initWithString:@"Hello" ]
NSString *str2 = str;
[ str2 retain ];
[ str release ];

In this example, the reference count for str is 2 because we called “[str2 retain]“.  When we release str, str2 will still exist.  This also implies that we have to remember to release str2 with a release call when we are done with it!

release

When we are done with an object, we have to manually release it by using the release keyword:

NSString *str = [ [ NSString alloc ] initWithString:@"Hello" ];
// ... do various stuff with the object str
[ str release ];   // return the memory allocated to str back to the memory heap.

When we use the release keyword on an object, it causes the reference count of that object to decrease by 1.  When the reference count reaches 0, the memory used by the object is released.

Do remember that we cannot release an object that is not owned by us (directly initialised or retained by us).

This example is wrong:

NSString *str = [ [ NSString alloc ] initWithString:@"Hello" ]
NSString *str2 = str;
[ str release ];
[ str2 release ];   // We cannot do this! since we do not own str2.

We only own an object when we alloc it explicitly or if we retain it. So this works:

NSString *str = [ [ NSString alloc ] initWithString:@"Hello" ]
 NSString *str2 = str;
[ str2 retain ];   // Here, we gain ownership of str2!
 [ str release ];
 [ str2 release ];   // So this won't break now.

Convenience Method and Autorelease

So far, we have learnt that all the objects we created using the alloc or new keywords are owned by us.  Consider the creation of an object using a convenience method:-

NSString *str = [ NSString stringWithFormat:@"%d", 4];

In this example, we do not own the str object because it is created using one of the convenience methods – static methods that are used for allocating and initializing objects directly.

This is OK:

NSString *str1 = [ [ NSString alloc ] initWithFormat:@"%d", 4 ];
 [ str1 release ];
 

This is NOT OK:

NSString *str2 = [ NSString stringWithFormat:@"%d",  4 ];
 [ str2 release ];   // Not OK, since we did not use alloc and so do not own str2.

So if we want to take ownership of an object when using a convenience method, we can do so with the retain keyword:

 NSString *str2 = [ [ NSString stringWithFormat:@"%d",  4 ] retain ];
 

Now that we have the ownership of str2, we can use either autorelease or release to reduce the reference count.

If we use the release keyword, we immediately reduce the reference count by 1 and the object str2 is immediately de-allocated from memory when the reference count reaches 0.

If we use the autorelease keyword, we are promising to reduce the reference count by 1 but not immediately and sometime later.

dealloc

We have now learnt how to use the alloc or new keyword to indicate ownership of an object.  We have also learnt how to release the objects we own by using the release or autorelease keywords.  In general, we should always release the objects as soon as we are done with them.  So if we created an object in a method, we should release it before we exit the method.  For properties, we can use the @property compiler directive together with the retain keyword like this:

@property (retain, nonatomic) NSString *name;

Because values of properties will be retained, it is important for us to free it before we exit the application.  A good place to do so is in the dealloc method of a class (such as a View Controller):

- (void) dealloc {
[ self.name release ];     // release the name property
[ super dealloc ];
}

The dealloc method is called whenever the reference count of its object reaches 0.  If we do not define the dealloc method in the class, its implementation in the base class will be called instead.

Micromanaging memory is part-and-parcel of iOS app development.  Learning to use alloc, new, release, autorelease and dealloc keywords will go a long way towards the production of a high performance app.