Memory Management

April 29th, 2009 by Chris Leave a reply »

iPhone SDK doesn’t use anything like Garbage Collection, you might now from the other programming languages. What does it mean? It means that whenever you create – alloc any new object, it’s “locked” in the memory until you release it. If you application terminates and you didn’t release it properly it will stay in the memory, so other application will crashed at any time when they need more memory than it available at that particular moment.

You shouldn’t think only about Memory Management, to be kind and to respect end-user and other developers work. If your application causes too many memory leaks, there is high likelihood that your application won’t pass Apple Revision. Using Memory Management properly you even help yourself. If your application generates a lot of object, but most of them are used only for a limited time, get rid of them as long as they are not necessary.

What is memory leak?

When you allocate the object or simply create a new object using any other method it’s unique name acts as a pointer to that class. I will give you an example. You have a method that displays an alert:

-(IBAction)showAlert {
	UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"message" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil];
	[alert show];
}

Whenever you call above method you generate a memory leak. You have allocated an object alert of type UIAlertView, but once this class is called, you don’t have any access to alert in any other method as it was allocated locally. Alert is displayed, pressing the Cancel button, hides it, but it stays in the memory, waiting for any other commands to execute. If you call this method again, although it allocs the next UIAlertView with the same name alert, it’s completely different object.

If you test this application with Instruments: Object Allocations/Memory Leaks, the number of UIAlertViews allocations will only grow. You can also use a NSTimer (in viewDidLoad method) and call this method frequently to understand the gravity of situation:

[NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(counter) userInfo:nil repeats:YES];

How to fix it? Add: [alert release];, after [alert show];. What does release acctualy do? It frees the memory, forgets about the pointer alert, so you can no longer use it, but the part of memory where the alert took, can be used again. Once you call release, it doesn’t mean that the object disappears from the user interface, but you have no longer access to its properties.

Let’s give another example, this time with UILabel. As you know, UILabel can be used to show single line text. Of course you can change it’s background color, text, shadows colors etc. But sometimes label can be more, sometimes less important. You can use the UILabel to show the current status of your application, some values, – so in this case UILabel is frequenlty changed (at least it text property). But you can also create the UILabel only to display some kind of header, static description, copyrights on the bottom, – and once you allocated it, you never change it again:

UILabel *copyrights = [[UILabel alloc] initWithFrame:CGRectMake(0,390,320,30)];
copyrights.text = @"(c) www.chris-software.com";
copyrights.backgroundColor = [UIColor clearColor];
[self.view addSubview:copyrights];
[copyrights release];

As you see, in above example I created UILabel, customized it a little bit, added it to the view and throwed it away from the memory. If I used the command [copyright release]; for example above [self.view addSubview:copyrights];, my app would unexpectly quited because of the error – when app wanted to add a subview it wouldn’t know what copyrights is.

And what if I frequently change the UILabel’s properties? I should define it in header file of current class (.h) and since then you have the access to this variable in any methods. You can alloc it in viewDidLoadloadView, any other method, or even in Interface Builder. Than release it once it’s not needed any more. When you are not sure if you need this label or not, don’t worry, you can release it in:

-(void)dealloc

dealloc method is one of the methods that are automatically called. For example in UIViewController, loadView method is called once you alloc the viewController (only if you implement this method), viewDidLoad is called when the view is added as a subview of something else for the first time. The same is with dealloc, but this method is called when the user quits the application. Inside this method in most cases you should release any object you mentioned in header file which was allocated either programmaticaly or in Interface Builder – you connected an object with an outlet.

Common mistakes

  1. You have in header file four menu buttons: IBOutlet UIButton *button1, *button2, *button3, *button4;, and the one another button UIButton *animateButton;. Only button1-4 were allocated somewhere. As I name the button animateButton, for sure I’m going to perform some constant animations on it. There is a magic trick, that allows you, using animateButton animate any of buttons button1-4. When in code, I type animateButton = button1, it doesn’t mean that animateButton is a copy of button1. It’s just a pointer, so from now, both animateButton and button1 refers to the same object. Later when I type animateButton = button2animateButton is pointing only to #2. So when it’s time to release buttons from the memory, I have to release only button1, button2, button3, button4, why not animateButton as well? Because I never allocated it, it was only the pointer to one of the buttons. And from the other way. If I type animateButton = button4, I can release animateButton, and now I don’t have to (I shouldn’t) release button4 and vice verse.
  2. You don’t have to release everything what has a “star”: * before the name. One of the examples I presented above. Just remember the number of alloc words should be equal to release. Although some objects can be allocated without alloc method. You can create an button using [UIButton buttonWithType:UIButtonTypeRoundedRect], but it doesn’t mean you don’t have to release it.
  3. NSTimer… Once you invalidated a timer, don’t release it. [myTimer invalidate] is enough.
  4. What about int, float, double, bool…? Forget about them.

Hope this article helped. I discussed with you everything using examples with alerts and labels. Here your leaks won’t be greater than few kilobytes each, what in sum can give you preattay big amount in megabytes later. Please don’t ignore it. Have you ever though what would happen with stability and performance of the device when you forget to release a 100MB movie? The more leaks generated the more often end-user has to reboot his iPhone / iPod Touch. Also, when possible use the lowest needed resolution images. Don’t add big images only to scale them down, and avoid compression like JPEG.

I can’t include any sample project here :-) . I don’t won’t to distribute projects with memory leaks signed with my name…

Advertisement

7 comments

  1. ugg says:

    It’s actually a cool and helpful piece of information. I’m happy that you shared this helpful info with us. Please keep us up to date like this. Thank you for sharing.

  2. Listen to my album I did together with my music production with J-Stalin, AP-9, Sweet Geez, City Side Crew and many more rappers from the bay area.

  3. Lynne Smisek says:

    I really like your blog.. very nice colors & theme. Did you create this website yourself or did you hire someone to do it for you? Plz answer back as I’m looking to design my own blog and would like to know where u got this from. thanks a lot

  4. Vish says:

    When i used UIbutton *button= [UIButton buttonWithType:UIButtonTypeRoundedRect];

    UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithCustomView:button];

    [button release];

    It gives error “_msg send”; and app hangs.

  5. Simon says:

    isn’t [UIButton buttonWithType:UIButtonTypeRoundedRect] autoreleased? i think it is Apple’s convention to return autoreleased objects when using these kind of helper methods.

Leave a Reply