Commençons par retain
y release
; autorelease
n'est en fait qu'un cas particulier une fois que vous avez compris les concepts de base.
En Cocoa, chaque objet garde la trace du nombre de fois qu'il est référencé (plus précisément, la balise NSObject
La classe de base l'implémente). En appelant retain
sur un objet, vous lui dites que vous voulez augmenter son nombre de références d'une unité. En appelant release
vous dites à l'objet que vous le lâchez, et son compte de référence est décrémenté. Si, après avoir appelé release
le nombre de références est maintenant égal à zéro, alors la mémoire de cet objet est libérée par le système.
La principale différence avec malloc
y free
est qu'un objet donné n'a pas à s'inquiéter du fait que d'autres parties du système se plantent parce que vous avez libéré la mémoire qu'elles utilisaient. En supposant que tout le monde joue le jeu et conserve/libère selon les règles, lorsqu'un morceau de code conserve puis libère l'objet, tout autre morceau de code faisant également référence à l'objet ne sera pas affecté.
Ce qui peut parfois prêter à confusion, c'est de savoir dans quelles circonstances vous devez appeler retain
y release
. Ma règle générale est que si je veux m'accrocher à un objet pendant un certain temps (s'il s'agit d'une variable membre d'une classe, par exemple), je dois m'assurer que le nombre de références de l'objet est au courant de mon existence. Comme décrit ci-dessus, le nombre de références d'un objet est incrémenté en appelant retain
. Par convention, il est également incrémenté (fixé à 1, en fait) lorsque l'objet est créé avec une méthode "init". Dans l'un ou l'autre de ces cas, il est de ma responsabilité d'appeler la méthode release
sur l'objet quand j'en ai fini avec lui. Si je ne le fais pas, il y aura une fuite de mémoire.
Exemple de création d'un objet :
NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed
Maintenant pour autorelease
. Autorelease est utilisé comme un moyen pratique (et parfois nécessaire) pour dire au système de libérer cet objet après un certain temps. Du point de vue de la plomberie, lorsque autorelease
est appelé, la fonction NSAutoreleasePool
est informé de l'appel. Le site NSAutoreleasePool
sait maintenant qu'une fois qu'il a une opportunité (après l'itération actuelle de la boucle d'événement), il peut appeler release
sur l'objet. De notre point de vue de programmeur, il s'occupe d'appeler release
pour nous, afin que nous n'ayons pas à le faire (et en fait, nous ne devrions pas).
Ce qu'il est important de noter, c'est que (encore une fois, par convention) toute création d'objet classe retournent un objet autoreleased. Par exemple, dans l'exemple suivant, la variable "s" a un nombre de références de 1, mais après la fin de la boucle d'événement, elle sera détruite.
NSString* s = [NSString stringWithString:@"Hello World"];
Si vous voulez vous accrocher à cette chaîne, vous devez appeler retain
explicitement, et ensuite explicitement release
quand vous aurez terminé.
Considérez le bout de code suivant (très artificiel), et vous verrez une situation dans laquelle autorelease
est nécessaire :
- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:@"Hello World"];
// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}
Je réalise que tout cela est un peu confus - à un moment donné, cependant, il y aura un déclic. Voici quelques références pour vous aider à démarrer :
-
Introduction d'Apple à la gestion de la mémoire.
-
Programmation Cocoa pour Mac OS X (4ème édition) par Aaron Hillegas - un livre très bien écrit avec beaucoup de bons exemples. Il se lit comme un tutoriel.
- Si vous voulez vraiment plonger, vous pouvez vous rendre à Big Nerd Ranch . Il s'agit d'un centre de formation dirigé par Aaron Hillegas - l'auteur du livre mentionné ci-dessus. J'y ai suivi le cours Intro to Cocoa il y a plusieurs années, et c'était une excellente façon d'apprendre.