2010-01-16 9 views
3

Je travaille sur une application et je voudrais m'assurer que je gère la mémoire correctement et libère tout ce que je devrais. Dans ma méthode viewDidLoad, j'alloue certaines variables pour déterminer quel arrière-plan appliquer à la vue (pour l'internationalisation) et l'application fonctionne correctement si je ne les libère pas.Gestion de la mémoire de l'iPhone

Le problème est que si je libère les variables, l'application va planter. Code de viewDidLoad est ci-dessous:

// 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]; 

Pourquoi se libérer du backgroundImageName et les variables de l'application provoquent langue crash?

Répondre

6
NSString *language = [[NSLocale preferredLanguages] objectAtIndex:0]; 

Ici, language n'a pas besoin d'être libéré parce que objectAtIndex: autoreleases pour vous. Par convention, vous possédez un objet si vous avez alloc ed, new ed, ou copy ed, sinon vous ne le faites pas.

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

Ici, l'objet UIColor n'a pas besoin d'être libéré (parce que vous alloc Éd).

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

Voici la chaîne retournée par [[NSString alloc] init] n'a pas besoin d'être libéré (parce que vous avez alloc Éd). Cependant, la ligne suivante change backgroundImageName pour indiquer une nouvelle chaîne auto-libérée, perdant la dernière référence à la chaîne d'origine sans la libérer (fuite de mémoire). backgroundImageName ne devrait pas être publié, car il est déjà autoeleased.

Vous pouvez éviter les fuites en libérant le UIColor et en éliminant la chaîne inutilisée. Par exemple:

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

... et ...

UIColor* backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:backgroundImageName]]; 
self.view.backgroundColor = backgroundColor; 
[backgroundColor release]; 
+0

explaination impressionnant. est parfaitement logique maintenant. Merci! –

0

réponse courte: lorsque vous créez un objet à l'aide des constructeurs qui n'ont pas le mot d'initialisation, alors vous n'êtes pas responsable de le relâcher

voir this pour plus d'explications

aussi la mémoire management guide est une excellente ressource Pour en savoir plus sur la gestion de la mémoire dans l'objectif c

0

Vous ne créez pas la chaîne de langue; vous revenez juste une référence. Seules les méthodes qui contiennent "new", "copy" ou "alloc" (par convention) renvoient des objets non auto-libérés. Pour toutes les autres méthodes, il est supposé que vous supprimerez la variable, donc si vous voulez le garder, vous DEVEZ le conserver. Le revers de la médaille est: vous ne devez pas libérer ces objets retournés, sauf si vous les avez conservés.

L'autre problème de ce code est que backgroundImageName est affecté deux fois. La première initialisation est en train d'être perdue. Débarrassez-vous-en, gardez le second et débarrassez-vous des deux appels, ils ne sont pas nécessaires.