Comment la version gérée pour @synthesized conserve-t-elle ses propriétés?

J’ai quelques questions sur les propriétés synthétisées dans Objective-C. La liste complète suit, mais la question de base est la suivante: comment le compilateur s’assure-t-il que les ivars pour les propriétés synthétisées sont correctement publiées, même si mon code peut ou non inclure des méthodes de publication dans dealloc?

Note: J’ai décidé de ne pas poster ces questions individuelles car elles sont étroitement liées et parce qu’il y a une poignée de questions existantes qui touchent les problèmes individuels sans vraiment aller au fond des choses.

Des questions quelque peu similaires:

  • La propriété retient-elle une libération?
  • Quelle est la différence entre la propriété et la synthèse?
  • Question sur l’atsortingbut Retenir avec la propriété et synthétiser

Configuration: considérez une classe avec une seule propriété:

@interface Person : NSObject { NSSsortingng * name; } @property (nonatomic, retain) name; @end 

Question n ° 1: Le cas très simple:

 @implementation Person @synthesize name; @end 

Avec cette configuration, je suppose que ce name sera automatiquement libéré à chaque fois qu’un object Person sera libéré. Dans mon esprit, le compilateur insère simplement [name release] dans la méthode dealloc comme si je l’avais tapé moi-même. Est-ce exact?


Question n ° 2: Si je choisis d’écrire ma propre méthode de dealloc pour cette classe et que j’omets un appel à [name release] , cela va-t-il fuir?

 @implementation Person @synthesize name; - (void)dealloc { [super dealloc]; } @end 

Question n ° 3: Si je choisis d’écrire ma propre méthode dealloc pour cette classe et d’ inclure un appel à [name release] , cela se traduira-t-il par une double version, puisque @synthesize a déjà pris en charge?

 @implementation Person @synthesize name; - (void)dealloc { [name release]; [super dealloc]; } @end 

Question # 4: Si je choisis d’écrire mon propre accesseur de propriété pour cette classe, mais que je n’écris pas ma propre méthode de dealloc , le name sera-t-il divulgué?

 @implementation Person @dynamic name; - (void)setName:(NSSsortingng *)newName { [newName retain]; [name release]; name = newName; } @end 

Question n ° 5: J’ai l’impression (sur la base de l’expérience) qu’aucun des scénarios ci-dessus n’entraînera de fuites ou de doubles publications, car la langue a été conçue pour les éviter. Cela, bien sûr, pose la question du “comment?”. Le compilateur est-il simplement assez intelligent pour suivre tous les cas possibles? Que faire si je devais faire ce qui suit (notez qu’il s’agit d’un exemple ridicule, juste pour illustrer mon propos):

 void Cleanup(id object) { [object release]; } @implementation Person @synthesize name; - (void)dealloc { Cleanup(name); } @end 

Est-ce que cela pourrait tromper le compilateur en ajoutant une autre [name release] à la méthode dealloc ?

Q1:

Non. @synthesize ne modifie pas -dealloc pour vous. Vous devez -release le name vous-même.

Q2:

Oui il va fuir Même raison que Q1.

Q3:

Non, il ne sera pas diffusé deux fois. Même raison que Q1.

Q4:

Oui il va fuir Même raison que Q1.

Q5:

Non, il ne sera pas diffusé deux fois. Même raison que Q1.


Vous pouvez le vérifier vous-même en -retain et -release et -dealloc pour signaler ce qui se passe.

 #import  @interface X : NSObject {} @end @implementation X -(oneway void)release { NSLog(@"Releasing %p, next count = %d", self, [self retainCount]-1); [super release]; } -(id)retain { NSLog(@"Retaining %p, next count = %d", self, [self retainCount]+1); return [super retain]; } -(void)dealloc { NSLog(@"Dealloc %p", self); [super dealloc]; } @end @interface Y : NSObject { X* x; } @property (nonatomic, retain) X* x; @end @implementation Y @synthesize x; - (void)dealloc { [x release]; [super dealloc]; } @end int main () { NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; Y* y = [[Y alloc] init]; X* x = [[X alloc] init]; yx = x; [y release]; [x release]; [pool drain]; return 0; } 

Dans Q1, Q2 et Q4, le dernier -retainCount de x est 1, il y a donc une fuite et dans Q3 et Q5, le dernier -retainCount est 0 et -dealloc est appelé, il n’y a donc pas de fuite.

De la documentation Objective-C sur les propriétés :

dealloc

Les propriétés déclarées remplacent fondamentalement les déclarations de méthode d’access. Lorsque vous synthétisez une propriété, le compilateur crée uniquement des méthodes d’accesseur absentes. Il n’y a pas d’interaction directe avec la méthode dealloc: les propriétés ne sont pas automatiquement libérées pour vous. Les propriétés déclarées constituent toutefois un moyen utile de vérifier l’implémentation de votre méthode dealloc: vous pouvez rechercher toutes les déclarations de propriétés dans votre fichier d’en-tête et vous assurer que les propriétés des objects non marquées sont libérées et que celles affectées sont affectées. non sorti.

Cela répond essentiellement à toutes vos questions.

La règle simple et générale: si vous allouez, conservez ou copiez un object, vous devez le libérer.

Lorsque vous utilisez le paramètre sémantique retain la définition dans une instruction @synthesize , vous demandez au compilateur de créer pour vous un dispositif de réglage qui retain sur l’object. Ni plus ni moins. Et comme vous conservez cet object (même si c’est via du code généré automatiquement par magie), vous devez le libérer et où le libérer est dans -(void)dealloc .

Quelque chose d’autre à savoir – si vous avez une propriété synthétisée, la définition de cette propriété sur nil (en utilisant la syntaxe à point, bien sûr) libère l’ivar pour vous.