Question

Encore un peu confus au sujet de la gestion de la mémoire Objective-C. Je pense que ma confusion vient de ce que signifie exactement le autorelease.

NSString *theBackendResponse = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSDictionary *accountDictionary = [theBackendResponse propertyList];
[viewController setAccountDictionary:accountDictionary];

Maintenant, que dois-je faire avec le accountDictionary dans la méthode setAccountDictionary de mon contrôleur de vue? En ce moment, je viens de définir la variable instance « accountDictionary » à tout ce qui est de retour. Dois-je mettre à une retenue, puis relâchez celui qui est retourné? Que dois mon look bloc de code setter comme, étant donné que la méthode de propertyList de NSString est autoreleased?

Par ailleurs, si je relâche theBackendResponse, vais-je perdre le accountDictionary? Je suppose que non ...

Était-ce utile?

La solution

L'appel [objectInstance autorelease] ajoute un objet à la NSAutoreleasePool actuelle. Lorsque ce pool reçoit un message drain, il envoie un release à tous les objets dans la piscine. Si l'un de ces objets de retainCount atteint 0, ils sont désallouées à ce moment-là. Le but de autorelease est de vous permettre de marquer un objet à libérer « un certain temps dans l'avenir ». Ceci est particulièrement utile pour des choses comme des méthodes qui renvoient un objet nouvellement alloué, mais veulent le libérer afin que l'appelant n'a pas à prendre possession de l'objet retourné. Une méthode pourrait ressembler à ceci:

- (id)myMethod {
    id myObj = [[SomeClass alloc] init];

    ...

    return [myObj autorelease];
}

L'appelant de myMethod serait retain alors la valeur de retour s'ils voulaient prendre possession de la valeur retournée ou de l'ignorer sinon. Lorsque le courant NSAutoreleasePool est drainée, myObj recevra un message de libération. Si aucun autre objet sont propriétaires (par exemple ont envoyé un message retain), il se désalloué.

Tout cela est expliqué dans le cacao Guide de programmation gestion de la mémoire . Même si vous avez déjà lu, il vaut toujours la peine d'une autre lecture.

Alors, pour répondre à vos questions:

D'abord, vous devez libérer theBackendResponse. Vous fuite de mémoire si vous ne le faites pas. Vous n'avez pas besoin de savoir ce que accountDictionary fait avec la chaîne: si elle a besoin de conserver une référence qu'il aura retenu theBackendResponse. Vous avez une propriété de theBackendResponse parce que vous alloc'd, donc vous devez renoncer à la propriété que (via release ou indirectement via autorelease).

Deuxièmement, vous devez conserver ou copier l'argument setAccountDictionary: si vous souhaitez conserver une référence à cet objet ou de la valeur respectivement. La méthode standard setter ressemble à quelque chose comme ceci (en supposant que vous ne avez pas besoin sémantique atomique):

-(void)setAccountDictionary:(NSDictionary*)newDict {
  if(newDict != accountDictionary) {
    id tmp = accountDictionary;
    accountDictionary = [newDict copy]; //Since newDict may be mutable, we make a copy so that accountDictionary isn't mutated behind our back.
    [tmp release];
  }
}

Vous devez aussi penser à release accountDictionary dans la méthode dealloc:

- (void)dealloc {
    [accountDictionary release];
    [super dealloc];
}

Puisque vous semblez utiliser NSViewController, je suppose que vous êtes sur Leopard (OS X 10.5) auquel cas, vous devriez probablement en utilisant @property et le @synthesized getter / setter si possible. Pour ce faire, ajoutez un

@property (copy,readwrite) NSDictionary * accountDictionary; 

déclaration à la @interface de classe. Et ajouter une directive @synthesize accountDictionary; dans le bloc @implementation pour votre classe contrôleur.

Autres conseils

En général, un objet ou une méthode ne devrait pas avoir à se soucier de la façon dont une autre est de gérer la mémoire. Le fait que quelqu'un d'autre a quelque chose autoreleased est hors de propos de vous. Il est plus simple de penser à la notion de propriété . Alors retain et d'autres méthodes revendiquent la propriété, et release et autorelease y renoncer. Si un objet doit conserver une référence à une autre, il faut revendiquer la propriété aussi longtemps que nécessaire. Ainsi, les méthodes setter généralement soit conserver ou copier la nouvelle valeur et libérer ou autorelease la valeur ancienne.

Je recommande fortement la lecture les directives de gestion de la mémoire Cocoa . Ils ne sont pas tout ce long ou compliqué, et il est très important de les comprendre.

La présente méthode accesseur doit toujours copy / retain la valeur entrante avant de libérer l'ancien, dans le cas où l'ancienne valeur est le seul objet qui est propriétaire de la nouvelle valeur:

-(void)setAccountDictionary:(NSDictionary*)newDict {
    id old = accountDictionary;
    accountDictionary = [newDict copy];
    [old release];
}

Si accountDictionary appelé newDict et le conserver pour le nombre newDict a été 1, l'appel à [accountDictionary release] avant l'appel à [newDict copy] causerait le compte à retenir obtenu à 0 et donc libérer newDict.

A titre d'exemple de code incorrect, où nous libérons le vieux dictionnaire et copiez le nouveau dictionnaire:

-(void)setAccountDictionary:(NSDictionary*)newDict {
    [accountDictionary release];
    accountDictionary = [newDict copy];
}

et avoir le code suivant:

NSDictionary *dict = [obj accountDictionary];
[obj setAccountDictionary:dict];

Il est artificiel, mais il démontre que dans le setter, accountDictionary et newDict se réfèrent à la même instance. Si le nombre est de retenir 1, la ligne de [accountDictionary release] diminuera le nombre de conserver à 0, et donc libérer l'instance de la mémoire. [newDict copy] va maintenant se référer à une instance non valide.

Apple décrit plusieurs concepts lors de la mise en œuvre accesseurs: gestion de la mémoire accesseur méthodes
Si vous pouvez utiliser Objective-C 2.0, j'aller avec des propriétés et la syntaxe à point. Les propriétés sont nouveaux en Objective-C 2.0 et offrent génération accesseur automatique.
Dans le fichier .h:

@property (retain) NSDictionary* accountDictionary;

Dans la mise en œuvre:

@synthesize accountDictionary;

Synthétiser génère des méthodes accesseurs pour votre NSDictionary. (Si vous voulez fournir votre propre implémentation, vous pouvez aussi le faire)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top