views:

267

answers:

4

Hi all,

I'm working on an app and I'd like to make sure that I'm managing memory properly and releasing everything that I should. In my viewDidLoad method I allocate some variables in determining which background to apply to the view (for internationalization) and the app works fine if I don't release them.

The problem is that if I release the variables the app will crash. Code from viewDidLoad is below:

// Set the background image based on the phone's preferred language
NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0];
NSString *backgroundImageName = [[NSString alloc] init];
backgroundImageName = [NSString stringWithFormat:@"background-%@.png",language];
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:backgroundImageName]];

... do some more initialization stuff ...

// IF THE FOLLOWING ARE RELEASED THE APP WILL CRASH!!!
//[backgroundImageName release];
//[language release];

Why would releasing the backgroundImageName and language variables cause the app to crash???

Thanks!

A: 

short answer : when you create an object using constructors that dont have the word init then you are not responsible for releasing it

see this for more explanation

also the memory management guide is an excellent resource to know more about memory management in objective c

Ahmed Kotb
A: 

You're not creating the language string; you're just getting back a reference. Only methods that have "new", "copy", or "alloc" in them (by convention) return non-autoreleased objects. For all other methods, it's assumed that you'll discard the variable, so if you want to keep it around, you MUST retain it. The flip side of this is: you should not release these returned objects unless YOU retained them.

The other problem in this code is that backgroundImageName is being assigned twice. The first initialization is being lost. Get rid of it, and just keep the second one, and get rid of both -release calls, they're not needed.

Ben Gottlieb
+5  A: 
NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0];

Here, language does not need to be released because objectAtIndex: autoreleases it for you. By convention, you own an object if you've alloced, newed, or copyed it, otherwise you don't.

self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:backgroundImageName]];

Here, the UIColor object does need to be released (because you alloced it).

NSString *backgroundImageName = [[NSString alloc] init];
backgroundImageName = [NSString stringWithFormat:@"background-%@.png",language];

Here the string returned by [[NSString alloc] init] does need to be released (because you've alloced it). However, the next line changes backgroundImageName to point to that a new autoreleased string, losing the last reference to the original string without releasing it (a memory leak). backgroundImageName should not be released because it is already autoreleased.

You can avoid the leaks by releasing the UIColor and eliminating the unused string. For example:

NSString *backgroundImageName = [NSString stringWithFormat:@"background-%@.png",language];

... and ...

UIColor* backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:backgroundImageName]];
self.view.backgroundColor = backgroundColor;
[backgroundColor release];
Will Harris
awesome explaination. makes perfect sense now. thanks!
John Frankes
A: 

This is a really nice post thank you for the explanation

madhavi