Erreur dans la doc Apple ?: satanées properties décidément !
ClicCool
Membre
Sans doutes me trompe-je mais je ne parvient pas à comprendre pourquoi, dans cet exemple de la doc, Apple fait un release sur une propriété implicitement assignée.
L'exemple se trouve dans The Objective-C Programming Language: Declared Properties: Example
Le code cité en exemple:
On y voit clairement que la property link n'a pas d'attribut et est donc Assign par défaut.
La classe adoptant le protocole implémente une variable d'instance pour supporter cette propriété.
Puis s'appuis sur @synthétize pour générer les accesseurs en précisant l'iVar à utiliser.
Les accesseurs ne sont pas sensés faire un retain sur une propriété Assign fusse seulement par défaut non ?
Mais alors pourquoi dans le dealloc Apple release-t-il cette iVar ? ???
L'exemple se trouve dans The Objective-C Programming Language: Declared Properties: Example
The Link protocol declares a property, next.
MyClass adopts the Link protocol so implicitly also declares the property next. MyClass also declares several other properties.../...
Le code cité en exemple:
@protocol Link<br />@property id <Link> next;<br />@end<br /> <br /> <br />@interface MyClass : NSObject <Link><br />{<br />Â Â NSTimeInterval intervalSinceReferenceDate;<br />Â Â CGFloat gratuitousFloat;<br />Â Â id <Link> nextLink;<br />}<br />@property(readonly) NSTimeInterval creationTimestamp;<br />@property(copy) NSString *name;<br />@property CGFloat gratuitousFloat;<br />@property(readonly, getter=nameAndAgeAsString) NSString *nameAndAge;<br /> <br />@end<br /> <br /> <br />@implementation MyClass<br /> <br />@synthesize creationTimestamp = intervalSinceReferenceDate, name;<br />// Synthesizing 'name' is an error in legacy runtimes;<br />// in modern runtimes, the instance variable is synthesized.<br /> <br />@synthesize next = nextLink;<br />// Uses instance variable "nextLink" for storage.<br /> <br />@dynamic gratuitousFloat;<br />// This directive is not strictly necessary.<br /> <br />- (CGFloat)gratuitousFloat {<br />Â Â return gratuitousFloat;<br />}<br />- (void)setGratuitousFloat:(CGFloat)aValue {<br />Â Â gratuitousFloat = aValue;<br />}<br /> <br /> <br />- (NSString *)nameAndAgeAsString {<br />Â Â return [NSString stringWithFormat:@"%@ (%fs)", [self name],<br />Â Â Â Â Â Â Â [NSDate timeIntervalSinceReferenceDate] - intervalSinceReferenceDate];<br />}<br /> <br /> <br /> - (id)init {<br />Â Â if (self = [super init]) {<br />Â Â Â Â intervalSinceReferenceDate = [NSDate timeIntervalSinceReferenceDate];<br />Â Â }<br />Â Â return self;<br />}<br /> <br />- (void)dealloc {<br />Â Â [nextLink release];<br />Â Â [name release];<br />Â Â [super dealloc];<br />}<br /> <br />@end
On y voit clairement que la property link n'a pas d'attribut et est donc Assign par défaut.
@property id <Link> next;
La classe adoptant le protocole implémente une variable d'instance pour supporter cette propriété.
id <Link> nextLink;
Puis s'appuis sur @synthétize pour générer les accesseurs en précisant l'iVar à utiliser.
@synthesize next = nextLink;
Les accesseurs ne sont pas sensés faire un retain sur une propriété Assign fusse seulement par défaut non ?
Mais alors pourquoi dans le dealloc Apple release-t-il cette iVar ? ???
[nextLink release];
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Tu as essayé le code sur un projet d'essai pour voir si ça crash ?
Ca peut valoir le coup d'utiliser les liens en bas de page pour signaler l'erreur si c'est bien le cas.
J'vais essayer d'implémenter un truc comme ça dès que j'ai une minute pour voir, avant d'éventuellement signaler ça à Apple.
Donc justement c'est plutôt dans le cas inverse que ça aurait marché dilaroga : self.next = nil fait un release ou non suivant si la @property associée est (retain) ou (assign).
Mais là c'est un message "release" qui est explicitement envoyé (qui décrémente le retainCount de la variable, mais ne la met pas à nil pour autant, ce qui fait à la limite qu'elle peut pointer sur un emplacement mémoire qui ne va plus rien représenter si le retainCount est passé à zéro suite à ce release et que l'objet a été désalloué, mais on s'en fiche on est dans le dealloc la variable ne peut plus être utilisée après ça de toute façon).
Alors que la @property ne fait pas de retain, et qu'il n'y a ni retain ni copy dans le reste du code sur cette variable next à priori... donc pourquoi le release... mystère.
D'accord mais l'ivar et la propriété sont intimement liées (à la compilation ou au runtime ?) par la déclaration
Si dans le code tu affectes directement une valeur à l'ivar nextLink :
c'est bien cette même valeur que tu récupéreras plus tard en passant par le getter
La correspondance semble fonctionner dans les deux sens ou bien je me trompe ?
Alors le release reçu par nextLink décrémente son retainCount et si le retainCount est à zéro la méthode -dealloc de cet objet est appelée afin de le détruire de la mémoire immédiatement (de sorte qu'un appel utltérieur à cet objet provoquera le plantage du programme). Donc, le release décrémente et désalloue au besoin. Donc ici si le retainCount est à zéro mais j'en doute une assignation devrait tout de même le faire passer à 1 (sinon comment s'en sortirait le pool de ramassage pour savoir ce qui est à détruire ou non ?) la référence sera bel et bien supprimée et tout prochain appel à nextLink povoquera une erreur tout comme un appel à next (puisque l'ivar et la propriété sont unies).
Envoyer un release sur une variable ne la passe pas à nil, même si cette variable est liée à une @property. Une @property ne fait que déclarer les setters et getters d'une variable.
Appeller [toto release] va envoyer un message release à toto comme [toto tata] va envoyer le message tata à toto. Ca ne va en aucun cas changer l'affectation de la variable à qui on envoie le message, en l'occurrence toto. Ca peut affecter l'état de l'objet référencé par la variable (l'objet pointé par la variable toto), mais la variable, elle, pointera toujours sur le même emplacement mémoire et ne sera pas affectée à un autre objet si on lui envoie juste un message.
Le lire déjà serait pas mal mais je ne l'ai pas trouvé par ici... ::)
Merci, c'est plus clair ainsi pour moi c'est l'affectation qui associe la propriété à une ivar d'un autre nom qui m'a perturbé.
Voilà où j'avais écrit ma prose
J'admets que ça peut être assez indigeste (j'avais pondu ça d'une traite sans trop formater ça proprement sous forme d'article ou de tuto propre) car beaucoup de texte, mais je suis parti d'un exemple qui met en avant à peu près tous les cas... j'espère que ça va t'aider à y voir plus clair ;D