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.
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. –
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. –
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. –