web-dev-qa-db-fra.com

Comment fonctionne le pool de libération automatique NSAutoreleasePool?

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];
}
94
James Sumners

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.

65
kperryua

NSAutoreleasePool: drain vs libération

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

37
mmalc

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 .

17
Neovibrant

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.

7
kperryua

J'ai trouvé que ce lien donnait la meilleure explication sur quand et comment utiliser NSAutoReleasePool: AutoReleasePool

1
Wayne Lo

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.

0
Hardik Mamtora

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

0
Antwan van Houdt

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

https://developer.Apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html

0
Gagan_iOS