2010-02-17 12 views
4

En Objective-C, je comprends que vous devez libérer tout ce que vous init/conserver/copier. Ai-je besoin de faire cela avant une déclaration return? Je veux comprendre l'appel release explicitement et ne pas utiliser autorelease.Libération de variables locales avant le retour?

-(void) someMethod 
{ 
    AnotherClass* ac = [[AnotherClass alloc] init]; 
    if([ac somethingHappens]){ 
    // Do I need to release ac here? 
    return; 
    } 
    [ac doSomethingElse]; 
    [ac release]; 
} 

Merci!

+0

C'est une mauvaise pratique d'avoir plusieurs routes de retour que vous avez dans le code ci-dessus, une explicite et une implicite.vous devriez déplacer le retour en dessous de [release], imaginer beaucoup d'if() déclarations que chacun a fait un retour, c'est beaucoup de code répétitif. –

+0

Pourquoi est-ce une mauvaise pratique, parce que c'est difficile à suivre? On dirait que suivre un tas de si la logique pourrait être tout aussi complexe. –

+0

il n'est pas maintenable quand vous avez 30 endroits que vous devez copier et dépasser un bloc de code de version, et quand vous ajoutez une chose à devoir [libérer] vous devez maintenant mettre à jour 30 places. Cela viole le principe DRY (ne vous répétez pas). La meilleure pratique si vous avez une valeur de retour est de définir la valeur de retour dans la logique, puis de renvoyer cette valeur au bas de la fonction, juste après votre seul point de [libérer] les blocs. –

Répondre

3

Oui, vous devez libérer vos variables, mais vous quittez la méthode.

C'est assez simple: quand vous init est quelque chose le nombre de retenue est incrémenté. Lorsque vous relâchez, il est décrémenté. Quand il atteint zéro, il est automatiquement libéré.

Dans votre code ci-dessus, vous initiez la variable, mais si elle suit la route de retour, le nombre de variables retenues ne devient jamais nul et, par conséquent, n'est jamais libéré.

+0

En fait, ce n'est pas quand vous 'init' quelque chose, mais quand vous' allouer 'quelque chose. Si votre méthode 'init' n'invoque pas [super init]', le nombre de rétention est toujours 1. – dreamlax

+0

Oh! C'est bon à savoir. J'ai modifié mon post ci-dessus. –

+0

@Stephen, merci, c'est ce que j'avais besoin de savoir. Je comprends mieux maintenant aussi. –

2

On suppose d'avoir une variable locale affectée comme suit

NSString *placeHolder = [NSString stringWithFormat:@"%@ %@",[someObject value1], [someObject value2]]; 

passer maintenant cette variable à une méthode définie par l'objet, comme setPlaceholder d'objet UISearchBar

[self.theSearchBar setPlaceholder:placeHolder]; 

Comment libérer dans le droit manière la chaîne assignée «placeHolder»?

Si vous pensez à autoreleas il:

NSString *placeHolder = [[NSString stringWithFormat:@"%@ %@",[someObject value1], [someObject value2]] autorelease]; 

votre code échouera avec un bad_exc_access

Si vous pensez à libérer la variable après passé à un autre endroit comme

[self.theSearchBar setPlaceholder:placeHolder]; 
[placeHolder release]; 

une exception d'exécution va jeter aussi.

Alors qu'est-ce qui ne va pas?

Le problème est le nombre de rétention. L'objet UISearchBar est alloué encore, donc si vous relâchez ou une telle variable auto-libération, appelée par cet objet, le nombre de retenir est toujours le même

NSLog(@"Retain count before assign to refer other object %d", [placeHolder retainCount]); 
[self.theSearchBar setPlaceholder:placeHolder]; 
NSLog(@"Retain count after referencing %d", [placeHolder retainCount]); 

Alors, comment gérer cette situation?

Essayez quelque chose comme le

suivant
[placeHolder retain]; // retainCount +1 
[self.theSearchBar setPlaceholder:placeHolder]; 
[placeHolder release]; // retainCount -1 

Ce que nous avons fait que? Jetons un coup d'oeil au nombre de retenir maintenant

NSLog(@"Retain count before doing retain %d", [placeHolder retainCount]); 
[placeHolder retain]; // retainCount +1 
NSLog(@"Retain count after retaining it %d", [placeHolder retainCount]); 

Ainsi, nous incrémentons le conserver avant de lui attribuer le nombre (Référencez par) à un objet, et - après - nous libérons localement cette variable.

C'est tout.

+0

Grande explication. – HotFudgeSunday