iPhone Basics: Memory Management

One of the biggest sources of confusion for new iPhone developers is memory management. If you’re accustomed to using convenient, garbage-collected scripting languages, you may be wondering why memory management is even necessary. Although Cocoa does support garbage collection, it was deemed too great an overhead for a phone platform. Therefore, it’s important for developers to know how to allocate and release objects correctly.

By following some simple guidelines, you can avoid the majority of memory management problems.

1. If you allocate an object, you should release it once you’re done.

When you allocate an object, you “own” that object, and you’re responsible for releasing it when you’ve finished using it:

Widget* widget = [[Widget alloc] init];
// Do something with widget...
[widget release];

You can think of release as saying relinquish ownership of this object, rather than destroy this object. Behind the scenes, Cocoa performs reference counting to keep track of ownership. If no one claims ownership, the object will be destroyed, and the memory it occupied will be reclaimed.

2. If you did not allocate an object directly, you should not release it.

Once you get the hang of release, it’s tempting to go around releasing objects when you shouldn’t. A common example is when you’re using factory methods:

NSString* label = [NSString stringWithFormat:@"Title: %@", widget.title];
// Do something with label
[label release] // Whoops, incorrect.

In this example, a new string object has been created, but we didn’t allocate it, and we don’t own it. Therefore, we must not call release here — doing so can cause an over-release, which can crash your app.

tip: How is this object released?

Behind the scenes, NSString has called autorelease on the string before returning it, which we’ll look at in a moment.

3. If you need an object, you should retain it (and release it when you’re done).

This rule applies when we receive an object that’s been created by someone else. For example, consider a setter method:

- (void)setName:(NSString*)newName;
{
    [newName retain];   // we need the new string object.
    [name release];     // we don't need the old string any more.
    name = newName;
}

retain signals that we claim ownership of the object; it will not be destroyed when the original owner releases it. But, now that we own the object, we must release it when we no longer need it. Under the hood, retain and release update the reference count of the object, incrementing and decrementing respectively.

Following this pattern simplifies memory management a great deal. When passing an object to a method, we can assume it will be retained (if necessary) and we can release it immediately afterwards:

UIButton* button = [[UIButton alloc] initWithFrame:myFrame];
[self.view addSubview:button]    // Here we can assume that view
                                 // has retained button,
[button release]                 // we can safely release it.

Another common example arises when we use collection objects, which retain the objects added to them:

NSMutableArray* widgetList = [[NSMutableArray alloc] init];
// ...
Widget* widget = [[Widget alloc] init];
[widgetList addObject:widget];           // retains widget
[widget release];                        // we can release widget
//...
[widgetList release] // objects in collection will be released.

4. If you create an object and don’t retain control of it, use autorelease.

Say you want to create your own factory method for Widget. Here, we create a new Widget object and return it from a class method:

+ (Widget*)createBetterWidget
{
    Widget* widget = [[Widget alloc] init];
    [widget setAwesome:11];
    return [widget autorelease];
}

We’re still responsible for releasing the object, so we call autorelease before returning it. autorelease signals that the object should be released “eventually.” The object is added to a pool that’s cleared at the end of an application run loop.

It may seem tempting to autorelease everything as a solution for memory management, however this is not recommended, as it’s possible for your app to run out of memory before the autorelease pool is drained.

The best approach is to take a simple, unambiguous approach to allocating and releasing objects. Follow these simple rules and you’ll be well on the way to creating bug-free and efficient code.

For in-depth coverage of these topics, the Apple Memory Management Programming Guide is essential reading for new developers.

Image credit: Dezeen

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

No Reader comments

Comments on this post are closed.