Commençons par retain
et release
; autorelease
est vraiment juste un cas spécial une fois que vous comprenez les concepts de base.
Dans Cocoa, chaque objet garde une trace du nombre de fois où il est référencé (en particulier, la NSObject
classe de base l'implémente). En appelant retain
un objet, vous lui dites que vous souhaitez augmenter son nombre de références de un. En appelant release
, vous dites à l'objet que vous le lâchez, et son nombre de références est décrémenté. Si, après l'appel release
, le nombre de références est maintenant nul, alors la mémoire de cet objet est libérée par le système.
La façon fondamentale dont cela diffère malloc
et free
est que tout objet donné n'a pas besoin de s'inquiéter de la panne d'autres parties du système parce que vous avez libéré la mémoire qu'ils utilisaient. En supposant que tout le monde joue et retient / libère selon les règles, lorsqu'un morceau de code conserve puis libère l'objet, tout autre morceau de code référençant également l'objet ne sera pas affecté.
Ce qui peut parfois prêter à confusion, c'est de connaître les circonstances dans lesquelles vous devez appeler retain
et 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 dans une classe, par exemple), je dois m'assurer que le nombre de références de l'objet me connaît. Comme décrit ci-dessus, le nombre de références d'un objet est incrémenté lors de l'appel retain
. Par convention, il est également incrémenté (mis à 1, vraiment) lorsque l'objet est créé avec une méthode "init". Dans l'un ou l'autre de ces cas, il est de ma responsabilité de faire appel release
à l'objet lorsque j'en ai fini avec lui. Sinon, il y aura une fuite de mémoire.
Exemple de création d'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) de dire au système de libérer cet objet après un certain temps. Du point de vue de la plomberie, lors de l' autorelease
appel, le thread actuel NSAutoreleasePool
est alerté de l'appel. Le NSAutoreleasePool
sait maintenant qu'une fois qu'il obtient une opportunité (après l'itération courante de la boucle d'événement), il peut appeler release
l'objet. De notre point de vue en tant que programmeurs, il prend soin de release
nous appeler , donc nous n'avons pas à le faire (et en fait, nous ne devrions pas).
Ce qui est important à noter, c'est que (encore une fois, par convention) toutes les méthodes de classe de création d'objet renvoient un objet publié automatiquement. Par exemple, dans l'exemple suivant, la variable «s» a un nombre de références de 1, mais une fois la boucle d'événements terminée, elle sera détruite.
NSString* s = [NSString stringWithString:@"Hello World"];
Si vous voulez vous accrocher à cette chaîne, vous devez l'appeler retain
explicitement, puis explicitement release
lorsque vous avez terminé.
Considérez le morceau de code suivant (très artificiel), et vous verrez une situation où 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 me rends compte que tout cela est un peu déroutant - à un moment donné, cependant, il cliquera. Voici quelques références pour vous lancer:
- Introduction d' Apple à la gestion de la mémoire.
- Cocoa Programming for Mac OS X (4e édition) , par Aaron Hillegas - un livre très bien écrit avec beaucoup de bons exemples. Cela se lit comme un tutoriel.
- Si vous plongez vraiment, vous pouvez vous rendre au Big Nerd Ranch . Il s'agit d'un centre de formation géré par Aaron Hillegas - l'auteur du livre mentionné ci-dessus. J'ai suivi le cours d'introduction au cacao il y a plusieurs années, et c'était une excellente façon d'apprendre.