Si je comprends bien, tout élément créé avec un alloc , new ou copy doit être libéré manuellement. Par exemple:
int main(void) {
NSString *string;
string = [[NSString alloc] init];
/* use the string */
[string release];
}
Ma question, cependant, est-ce que cela ne serait pas aussi valable?
int main(void) {
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
NSString *string;
string = [[[NSString alloc] init] autorelease];
/* use the string */
[pool drain];
}
Oui, votre deuxième extrait de code est parfaitement valide.
Chaque fois que -autorelease est envoyé à un objet, il est ajouté au pool de libération automatique le plus interne. Lorsque le pool est vidé, il envoie simplement -release à tous les objets du pool.
Les pools autorelease sont simplement une commodité qui vous permet de différer l'envoi-release à "plus tard". Ce "plus tard" peut se produire à plusieurs endroits, mais le plus courant dans les applications de l'interface graphique Cocoa se situe à la fin du cycle de la boucle d'exécution en cours.
Étant donné que les fonctions de drain
et release
semblent semer la confusion, il peut être utile de le préciser ici (bien que cela soit traité dans la documentation ...).
Strictement parlant, dans la perspective globale, drain
est pas équivalent à release
:
Dans un environnement compté de références, drain
effectue les mêmes opérations que release
, de sorte que les deux sont équivalentes en ce sens. Pour souligner, cela signifie que vous non ne perdez pas un pool si vous utilisez drain
plutôt que release
.
Dans un environnement collecté par les ordures, release
est un no-op. Ainsi, cela n'a aucun effet. drain
, en revanche, contient un indice pour le collectionneur qu'il doit "collecter si nécessaire". Ainsi, dans un environnement de récupération, l’utilisation de drain
aide le système à balayer la collecte.
Comme déjà indiqué, votre deuxième extrait de code est correct.
Je voudrais suggérer une manière plus succincte d’utiliser le pool autorelease qui fonctionne sur tous les environnements (comptage de références, GC, ARC) et évite également la confusion entre drain et rejet:
int main(void) {
@autoreleasepool {
NSString *string;
string = [[[NSString alloc] init] autorelease];
/* use the string */
}
}
Dans l'exemple ci-dessus, veuillez noter le bloc @autoreleasepool. Ceci est documenté ici .
Non vous vous trompez. La documentation indique clairement que sous non GC, -drain est équivalent à -release, ce qui signifie que NSAutoreleasePool aura pas une fuite.
J'ai trouvé que ce lien donnait la meilleure explication sur quand et comment utiliser NSAutoReleasePool: AutoReleasePool
envoyer autorelease au lieu de relâcher vers un objet prolonge la durée de vie de cet objet au moins jusqu'à ce que le pool lui-même soit vidé (il peut être plus long si l'objet est conservé ultérieurement). Un objet peut être placé dans le même pool plusieurs fois, auquel cas il reçoit un message de libération pour chaque fois qu'il a été placé dans le pool.
oui, votre code est parfait, si vous utilisiez la collecte de déchets, il vous suffirait de définir la chaîne sur nil lorsque vous en aurez terminé. Le ramassage des ordures n'est pas bon pour la performance de votre application, donc je ne recommanderais pas de l'utiliser: P
Ce que j'ai lu dans Apple: "À la fin du bloc de pool de libération automatique, un message de libération est envoyé aux objets ayant reçu un message de relâche automatique - un objet reçoit un message de libération à chaque fois qu'un message de libération automatique est envoyé le bloc."