Saletés de @property(retain) à  releaser !

AliGatorAliGator Membre, Modérateur
octobre 2009 modifié dans Objective-C, Swift, C, C++ #1
Hello,

Comme j'en ai marre dans mes programmes, où j'utilise massivement des @property(retain), de devoir releaser mes variables dans le dealloc, je me suis attaqué au problème.
J'ai donc fait une catégorie de NSObject pour lui rajouter une méthode, qui va parcourir toutes les @property(retain) ou @property(copy) et releaser tout seul les variables associées.

Dites-moi ce que vous en pensez, je suis preneur de commentaires sur le code, et j'ai p'tet oublié des cas alambiqués...
#import &lt;Foundation/Foundation.h&gt;<br /><br />@interface NSObject(AutoDealloc)<br />+(void)releasePropertiesOfObject:(id)object;<br />@end

#import &quot;NSObject+AutoDealloc.h&quot;<br />#import &lt;objc/runtime.h&gt;<br /><br />@implementation NSObject(AutoDealloc)<br />+(void)releasePropertiesOfObject:(id)object<br />{<br />	// Warning, &#39;self&#39; here is a Class!<br />	NSAssert([object isKindOfClass:self],@&quot;releasePropertiesOfObject: inconsistent object passed as argument&quot;);<br />		<br />	unsigned int propertiesCount;<br />	objc_property_t* properties = class_copyPropertyList(self, &amp;propertiesCount);<br />	for (unsigned int i=0; i &lt; propertiesCount; i++)<br />	{<br />		objc_property_t property = properties[i];<br />		const char* attr = property_getAttributes(property);<br />		if ( (strstr(attr,&quot;,&amp;,&quot;)!=NULL) || (strstr(attr,&quot;,C,&quot;)!=NULL) ) // (retain) || (copy)<br />		{<br />			// this prop is (retain) or (copy) so find the backing store variable<br />			const char* backingVar = strstr(attr,&quot;,V&quot;);<br />			if (backingVar) // if we have a variable attached to this property, release it<br />			{<br />				const char* varName = backingVar+2;<br />				void* varValue;<br />				object_getInstanceVariable(object,varName,&amp;varValue);<br />			<br />				[(id)varValue release];<br />			} else {<br />				// a @property(retain) or @property(copy)<br />				// but without an instance variable attached... so what to do?<br />			}<br />		}<br />	}<br />	free(properties);<br />}<br />@end


Exemple d'utilisation :
@interface Dummy : NSObject {<br />&nbsp; int _machin;<br />&nbsp; NSArray* unTableau;<br />&nbsp; IBOutlet UILabel* label;<br />}<br />@property(assign) int machin;<br />@property(retain) NSArray* truc;<br />@property(retain) NSString* labelText;<br />@end<br /><br />@implementation Dummy<br />@synthesize machin = _machin, truc = unTableau;<br />-(NSString*)labelText { return label.text; }<br />-(void)setLabelText:(NSString *)txt { label.text = txt; }<br /><br />-(void)dealloc<br />{<br />&nbsp; [Dummy releasePropertiesOfObject:self]; // fait un release sur unTableau et _machin<br />&nbsp; [super dealloc];<br />}<br />@end


Notes :
  • J'ai pas trouvé de possibilité de présenter ma méthode sous forme d'une méthode d'instance, de sorte qu'on puisse l'appeler genre [tt][self releaseProperties][/tt]... car je n'ai pas trouvé de moyen de détecter la classe "logique" de l'objet self (seulement la classe réelle via [tt][self class][/tt])... ce qui pose problème quand la méthode est appelée récursivement via des [tt][super dealloc][/tt] puisque [tt][self class][/tt] retournera la même classe au fur et à  mesure de la remontée dans la hiérarchie, donc boum...
  • C'est pour ça que j'ai fait une méthode de classe, permettant d'avoir un accès à  la classe "logique" et de parer à  tous les cas genre [tt]Parent* p = [[[Enfant alloc] init] autorelease];[/tt]. Mais si vous avez une meilleure idée de ce côté...?
  • Je me demande que faire dans le cas où l'on a une @property(retain) non associée à  une variable d'instance (mais implémentée à  la main), comme [tt]labelText[/tt] dans mon exemple ? Pour l'instant je fais rien, mais devrais-je affecter la propriété à  nil ou autre ? Votre avis ?

Réponses

  • schlumschlum Membre
    22:36 modifié #2
    Déjà  je comprends pas trop l'intérêt des properties (du fait du temps d'implémentation des setters / getters négligeable par rapport au temps total de codage d'un projet), mais alors là  c'est pousser le vice de la flemme loin  :)
  • ClicCoolClicCool Membre
    22:36 modifié #3
    Ben ça m'intéresse bien ton truc Ali  :o


    P.S. j'ai jamais dit que j'étais pas flemmard moi ;)
  • AliGatorAliGator Membre, Modérateur
    octobre 2009 modifié #4
    @schlum :

    Ce que j'aime des @properties c'est que ça évite d'implémenter le setter et le getter, et en plus ça synthétise bien les propriétés (au sens commun du terme) de la classe, que tu vois du coup en un coup d'oeil, au lieu d'avoir plein de [tt]-(Type)machin[/tt] et [tt]-(void)setMachin:(Type)x[/tt].

    Après, dans tous les cas de toute façon il faut faire un release sur tes variables d'instances dans ton dealloc, que tu utilises les @properties ou pas ! Donc ça ne change pas le problème de devoir faire tout plein de release dans ce dealloc...

    Car en fait écrire une ligne @property T toto dans le .h pour moi est tout simplement exactement équivalent à  écrire les 2 lignes [tt]-(T)toto[/tt] et [tt]-(void)setToto:(T)v[/tt], côté header. Et d'en profiter pour indiquer ta politique de gestion mémoire associée. Côté .m, ça te permet si tu le souhaites d'implémenter automatiquement le setter et getter... ou pas, comme tu veux !

    Sauf que si tu n'utilises pas les @properties, tu seras aussi obligé de faire les release à  la main. Alors que si tu utilises @property, avec mon code tu peux juste faire [tt][TaClasse releasePropertiesOfObject:self];[/tt] et ça le fait tout seul. Ce que tu ne peux encore pas faire si tu n'utilises pas les @property.



    Après, chacun sa façon de coder, et chacun ses préférences, mais moi quand je compare ces 2 possibilités, mon choix est tout trouvé ;D
    @interface Dummy : NSObject {<br />  NSString* str1;<br />  NSString* str2;<br />  NSString* str3;<br />}<br />-(void)setStr1:(NSString*)val;<br />-(NSString*)str1;<br />-(void)setStr2:(NSString*)val;<br />-(NSString*)str2;<br />-(void)setStr3:(NSString*)val;<br />-(NSString*)str3;<br />@end<br /><br />@implementation Dummy<br />-(void)setStr1:(NSString*)val<br />{<br />  @synchronized(self)<br />  {<br />    if (val != str1)<br />    {<br />      [str1 release];<br />      str1 = [val retain];<br />    }<br />  }<br />}<br />-(NSString*)str1<br />{<br />  return str1;<br />}<br />-(void)setStr2:(NSString*)val<br />{<br />  @synchronized(self)<br />  {<br />    if (val != str2)<br />    {<br />      [str2 release];<br />      str2 = [val copy];<br />    }<br />  }<br />}<br />-(NSString*)str2<br />{<br />  return str2;<br />}<br />-(void)setStr3:(NSString*)val<br />{<br />  if (val != str3)<br />  {<br />    [str3 release];<br />    str3 = [val retain];<br />  }<br />}<br />-(NSString*)str3<br />{<br />  return str3;<br />}<br />-(void)dealloc<br />{<br />  [str1 release];<br />  [str2 release];<br />  [str3 release];<br />  [super dealloc];<br />}<br />@end
    
    @interface Dummy : NSObject {<br />  NSString* str1;<br />  NSString* str2;<br />  NSString* str3;<br />}<br />@property(retain) NSString* str1;<br />@property(copy) NSString* str2;<br />@property(nonatomic,retain) NSString* str3;<br />@end<br /><br />@implementation Dummy<br />@synthesize str1, str2, str3;<br />-(void)dealloc<br />{<br />  [Dummy releasePropertiesOfObject:self];<br />  [super dealloc];<br />}<br />@end
    
  • CeetixCeetix Membre
    22:36 modifié #5
    J'avoue c'est super pratique, déjà  que taper les @property c'est lourd alors en plus remplir le dealloc ... Vraiment bonne ton idée Ali ! Je testerai ça dans ma prochaine app ;)
  • 22:36 modifié #6
    Fallait y penser à  ton truc Ali en effet. Mais perso je préfère être sûr de ce qui se passe dans mon dealloc. Question d'habitude sans doute.
    Enfin pour l'instant ça me dérange pas de faire un simple "self.toto=nil;" même si j'en ai 10 à  mettre :p À force de tout masquer, on fini par ne plus s'en soucier, et ça je préfère pas  >:)
  • schlumschlum Membre
    22:36 modifié #7
    Les @synchronized sont ajoutés automatiquement par les properties ?  ???
    Parce que mettre des mutex quand il n'y en a pas besoin, c'est sacrement lourd !
  • AliGatorAliGator Membre, Modérateur
    octobre 2009 modifié #8
    Mais mais mais, schlum, qu'est-ce qui t'arrive ?!
    Tu n'es pas au courant des nouveautés de Xcode 3.2 avec l'intégration de Clang/LLVM dedans, et maintenant tu n'es pas au courant de tous les avantages des @properties ? Mais ce n'est plus le schlum que je connais ça ;D

    Oui @synthesize rajoute ce qu'il faut... en fonction des attributs que tu mets à  ta @property bien sûr. Si tu veux pas les mutex, tu mets un [tt]nonatomic[/tt] et basta ;)
    • Si tu déclares @property(retain), ça fait le retain, et le release de la valeur précédente, et ce entouré de @synchronize, et ce que j'ai oublié aussi, ça rajoute toutes les méthodes de KVO ([tt]willChangeValueForKey:[/tt], [tt]didChangeValueForKey:[/tt]...)
    • Si tu déclares @property(nonatomic, retain), ça fait le retain, le release sur la valeur précédente, le KVO, mais ça fait pas le @synchronize puisque tu demandes explicitement nonatomic.
    • Si tu déclares @property(copy) ça fait le copy et le release et le KVO
    • Si tu déclares @property(nonatomic, assign) ça fait juste une affectation (et le KVO)


    Etc, etc, bref, justement ce qui est bien avec @property c'est que ça gère pour nous tous les cas tout seul sans rien oublier ;D C'est ce qui fait aussi la beauté des @property ! :)

    Mais après, si tu veux pas utiliser @synthesize, ça t'empêche pas d'utiliser @property (et d'implémenter ton setter et getter toi-même).

    Et puis entre nous, tout ça combiné à  mon petit "User Script" que j'ai rajouté à  Xcode pour qu'il copie mes déclarations de variables d'instances sélectionnées et génère les @property(nonatomic, retain|assign) associés tout seul... y'a vraiment plus grand chose à  taper comme code sérieux. Le temps que je gagne au niveau du dev de ce côté loin d'être négligeable avec tout ça :)

    PS : J'ai édité mon exemple plus haut de comparaison avec/sans @property pour montrer 3 cas différents
  • ClicCoolClicCool Membre
    22:36 modifié #9
    dans 1256336670:
    .../...À force de tout masquer, on fini par ne plus s'en soucier, et ça je préfère pas  >:)

    ça peut être une bonne habitude que de pas trop compter sur les automatismes ...


    dans 1256336670:
    .../...Enfin pour l'instant ça me dérange pas de faire un simple "self.toto=nil;" .../...


    En attendant tu utilises le Garbage Collector apparemment, non ?  :P
  • AliGatorAliGator Membre, Modérateur
    octobre 2009 modifié #10
    dans 1256336670:

    Enfin pour l'instant ça me dérange pas de faire un simple "self.toto=nil;" même si j'en ai 10 à  mettre :p

    [tt]self.toto = nil[/tt] permet en effet, puisqu'il appelle du coup le setter [tt][self setToto:nil];[/tt], de faire un release au final. Sauf que c'est ce que je faisais au début aussi... avant de lire des articles m'expliquant que ce n'était pas la meilleure des pratiques, et qu'il était préférable de faire un release sur la variable d'instance directement.
    On avait eu une discussion sur PommeDev récemment à  ce sujet d'ailleurs.

    Dans les cas où les setters ont des mécanismes de dépendances (déclenchement des KVO, code perso si tu as personnalisé ton setter qui pourrait appeler d'autres objets... potentiellement déjà  désalloués à  ce moment dans le dealloc... ce genre de trucs) ça peut poser des problèmes et des prises de têtes. Alors qu'un appel direct au release, c'est plus simple/atomique comme action et avec moins de conséquence.

    dans 1256336670:
    À force de tout masquer, on fini par ne plus s'en soucier, et ça je préfère pas  >:)
    Bah justement, moi à  force d'avoir des modifications de specs (saleté de MOA :P) et donc d'avoir à  modifier parfois mes classes au fur et à  mesure de l'avancement de mon projet, pour rajouter des variables d'instances par-ci par-là ... j'en arrive vite à  oublier justement de releaser une variable que j'avais rajoutée (Et pour ça Clang loupe souvent le coche et ne me signale rien...). Et quand on commence à  avoir 60 classes avec des v.i. retainé de partout et pas le temps de faire de la review de code, ...
  • ClicCoolClicCool Membre
    22:36 modifié #11
    Ah!

    Autant pour moi alors  o:)

    Soit ma mémoire n'est pas si bonne, soit y'a eu des évolutions qui m'échappent encore.

    PS pour les dents de la lumière des WC c'est fait  :P
  • octobre 2009 modifié #12
    dans 1256338386:

    dans 1256336670:
    À force de tout masquer, on fini par ne plus s'en soucier, et ça je préfère pas  >:)
    Bah justement, moi à  force d'avoir des modifications de specs (saleté de MOA :P) et donc d'avoir à  modifier parfois mes classes au fur et à  mesure de l'avancement de mon projet, pour rajouter des variables d'instances par-ci par-là ... j'en arrive vite à  oublier justement de releaser une variable que j'avais rajoutée (Et pour ça Clang loupe souvent le coche et ne me signale rien...). Et quand on commence à  avoir 60 classes avec des v.i. retainé de partout et pas le temps de faire de la review de code, ...


    Ha.. tu m'as convaincu sur le coup  :)
    D'un autre côté ça nous permet aussi de porter plus d'attention à  notre code  :adios!: Mais bon j'avoue quand même être séduit.. Bien que ça me fasse un peu chier de devoir inclure ta catégorie de NSObject dans chacun des nouveaux projets. À force on se retrouve à  inclure plein de fichiers de ce genre à  chaque fois qu'on fait un nouveau projet, en plus des framework (Sparkle, etc..)
    Tiens d'ailleurs, n'y a-til pas la possibilité de dire à  XCode d'ajouter des fichiers directement à  la création d'un projet de type iPhone ou Mac ?
  • AliGatorAliGator Membre, Modérateur
    22:36 modifié #13
    @ClicCool

    La syntaxe pointée est apparue avec Objective-C 2.0. Depuis, on peut donc écrire [tt]self.toto = a;[/tt] qui est exactement équivalent à  [tt][self setToto:a];[/tt], et écrire [tt]a = self.toto;[/tt] qui est exactement équivalent à  [tt]a = [self toto];[/tt].

    Après, la syntaxe pointée, on aime ou on aime pas (et on peut utiliser ou non, qu'on utilise les @property ou pas, ce sont deux choses décorrélées). Mais faut bien avoir en tête que [tt]self.toto = a[/tt] du coup est bien différent de [tt]toto = a[/tt] puisque dans le dernier cas ça fait une simple affectation... alors que dans le premier cas ça appelle le setter (qui peut très bien ne faire qu'une simple affectation, remarque, mais fait plus probablement un release de l'ancienne valeur, un retain de la nouvelle, etc... bref gère la mémoire comme il faut comme tout bon setter qui se respecte)
  • ClicCoolClicCool Membre
    22:36 modifié #14
    dans 1256339264:
    .../..Mais faut bien avoir en tête que [tt]self.toto = a[/tt] du coup est bien différent de [tt]toto = a[/tt] puisque dans le dernier cas ça fait une simple affectation... alors que dans le premier cas ça appelle le setter (qui peut très bien ne faire qu'une simple affectation, remarque, mais fait plus probablement un release de l'ancienne valeur, un retain de la nouvelle, etc... bref gère la mémoire comme il faut comme tout bon setter qui se respecte)


    Merci Ali :)

    C'est justement ce que je n'avais pas réalisé pleinement.

    J'utilise cette syntaxe pointée et je joue même de la  différence entre la simple affectation [tt]toto = a[/tt] et la pointée [tt]self.toto = a[/tt] pour shunter ou pas le setter et donc le KVObserving, mes chers binding et l'undoManager.

    MAIS mon apréhension de la syntaxe n'avait pas été jusqu'à  pleinement réaliser ce que faisait le setter obligeament mis à  disposition par l'ObjC2. Plus exactement je le savais, mais ce n'était pas suffisemment assimilé par mon esprit pour avoir toujours conscience des implications.
    MERCI !

    C'est un argument de plus pour ce méfier des "boites noires" que l'on peut utiliser sans avoir complètement conscience de ce qu'elle font....
  • schlumschlum Membre
    octobre 2009 modifié #15
    Oui, donc c'est bien ce que je dis, par défaut il met des mutex partout  :P
    Pour avoir fait des tests entre modification directes, modifications " atomiques " (des libs atomic) et modifications avec mutex, il y a une perte d'optimisation très nette à  chaque étape.  ;)
    Et c'est quand même assez rare d'avoir besoin d'un mutex dans des setters / getters.
    Et quand t'as besoin d'une gestion atomique sur un u64 et que tu ne veux pas de mutex, tu peux utiliser des fonctions atomiques automatiquement avec les "properties" ? ("man atomic") :P

    Sinon, non, je n'utilise aucune nouveauté d'Objective-C 2.0, ça n'apporte pas grand chose d'intéressant ; au contraire, ça rend le code beaucoup moins lisible (à  mon sens bien sûr)...
  • muqaddarmuqaddar Administrateur
    22:36 modifié #16
    Dis moi Ali, ton code ne release que les properties ?
    Par exemple, si on a une ivar mais pas de property dessus, il faut quand même penser à  la releaser dans dealloc ? Il faudrait donc faire gaffe aux ivars sans ou avec property... Ou alors il release tout (et dans ce cas, ça peut être dangereux si l'objet n'a pas été alloué avec l'ivar dans le code ?)

  • 22:36 modifié #17
    Non ça release que les @property qui ont un mode retain ou copy  :o
  • ClicCoolClicCool Membre
    octobre 2009 modifié #18
    dans 1256333424:
    .../...
    .../...<br />				// a @property(retain) or @property(copy)<br />				// but without an instance variable attached... so what to do?<br />			}.../...
    



    Peut-être qu'ici y'a moyen d'afiner en testant le Runtime ?:

    • Si c'est un runtime d'ObjC2 ("modern rutime") l'iVar est "synthétisée" même si elle n'est pas déclarée dans l'interface
      -> on la libère

    • Si c'est le "legacy runtime" ... ben je sais pô.




    [EDIT] Suis-je bête, pas besoin de tester le runtime puisque ton backingVar existera que l'ivar soit déclaré dans l'interface ou synthétisé par le runtime.

    Reste donc le cas de figure de l'absence d'iVar.
    Dans le doutes tu l'ignores c'est le mieux en effet.
  • ClicCoolClicCool Membre
    22:36 modifié #19
    dans 1256373064:
    .../...
    Pour avoir fait des tests entre modification directes, modifications " atomiques " (des libs atomic) et modifications avec mutex, il y a une perte d'optimisation très nette à  chaque étape.  ;).../...


    T'as raison Schlum, et c'est documenté en effet:
    The effect of the nonatomic attribute depends on the environment. By default, the synthesized accessors are atomic. In a reference counted environment, guaranteeing atomic behavior requires the use of a lock; moreover a returned object is retained and autoreleased, as illustrated in “Atomicity.” If such accessors are invoked frequently, this may have a significant impact on performance.../...


    Ce serait même un argument pour utiliser le Garbage Collector !! :P:
    .../...In a garbage collected environment, most synthesized methods are atomic without incurring this overhead
  • muqaddarmuqaddar Administrateur
    22:36 modifié #20
    Mais pourquoi Ali lance des discussions comme ça juste avant de partir en week-end ? ça m'empêche de faire la sieste dans l'herbe à  la campagne sans y penser. :)beta:
  • ClicCoolClicCool Membre
    22:36 modifié #21
    dans 1256391860:

    Mais pourquoi Ali lance des discussions comme ça juste avant de partir en week-end ? ça m'empêche de faire la sieste dans l'herbe à  la campagne sans y penser. :)beta:

    :p Je me faisai exactement la même réflexion y'a 5 minutes !!!  :p
  • AliGatorAliGator Membre, Modérateur
    22:36 modifié #22
    Parce que c'est bien plus marrant, d'autant que je suis justement parti en WE de mon côté sans toucher au net pendant ces 2 jours, donc à  vous laisser mariner là -dedans tout seuls ;D

    @Schlum : oui par contre je suis tout à  fait d'accord, j'ai jamais compris pourquoi par défaut dans le langage ils avaient fait en sorte que par défaut les @property soient atomic (et qu'il faille indiquer "nonatomic" pour ne pas avoir les mutex), j'aurais pour ma part carrément préféré l'inverse aussi.

    Bon en même temps maintenant je m'en fiche puisque je n'écris même plus ces lignes (je fais un Pomme-Alt-Ctrl-P sur mes ivar pour lesquelles je veux qu'elles soient des propriétées (ce qui n'est pas forcément le cas de toutes), et un Pomme-V et mes "User Scripts" que j'ai créé dans Xcode m'écrivent les lignes tout seuls donc je me pose plus la question moi :D Mais je suis bien d'accord, j'aurais préféré "nonatomic" par défaut, et un mot clé "atomic" possible si on veut les mutex, et pas l'inverse !
    Ceci dit comme je le disais plus haut, l'un n'empêchant pas l'autre, tu n'es pas obligé d'utiliser toutes les nouveautés d'Objective-C 2.0 en même temps. Rien ne t'empêche de déclarer tes setters/getters avec une ligne @property (au lieu d'une ligne [tt]machin[/tt] et [tt]setMachin:[/tt]), mais de continuer de les implémenter toi-même (avec ou sans mutex selon tes besoins, avec ou sans KVO selon tes besoins, avec les fonctions de atomic.h ou pas, en utilisant une ivar ou pas si ta property est dérivée, ça n'empêche pas. C'est pas parce que tu déclares tes propriétées ayant un getter+un setter via @property au lieu de via [tt]machin[/tt] et [tt]setMachin:[/tt] que tu es obligé d'utiliser @synthesize dans le .m !!


    @Alex : Oui ça ne libère que les @property déclarées retain ou release, pas du tout les autres ivar (où de toute façon par contre pour ça je trouve que ça serait une mauvaise idée, car comment savoir si tu as effectivement fait un retain sur ces ivars ? Parce que bon certes c'est souvent le cas, du moins pour les ivar de type NSObject, pas pour les types atomiques genre int ou float... Sauf pour les delegate, les dataSource, et autres références.... Bref pour moi ça c'est plutôt au cas par cas.
    Un peu comme pour les @property... sauf que l'avantage des @property c'est justement qu'on indique aussi la politique/rôle qu'on donne à  cette propriété (retain ou copy ou assign, etc) et que du coup là  on sait qu'on respecte les règles mentionnées dans le .h avec ma méthode.


    @Hervé : Oui, pour les @property non associées à  une ivar (setMachin:(T)v et -(T)machin qui ne modifient ou retourne pas la valeur d'une ivar machin mais dérivent cette valeur ou font tout autre chose, quoi), c'est un peu des cas particulier et au cas par cas, donc c'est pour ça que je me suis dit comme toi, autant ne rien faire.
    Le but de mon code releasePropertiesOfObject: c'est de remplacer parfois 10 ou 20 lignes de [machin release] par une seule ligne... Mais ça n'empêche pas qu'il faut écrire le [super dealloc], et releaser les ivar qui ne sont pas en @property... donc si y'a aussi des cas particulier à  gérer, il est encore temps de les faire à  la main au cas par cas aussi ;)
  • muqaddarmuqaddar Administrateur
    22:36 modifié #23
    Salut Ali,

    Tiens, un article vient de tomber sur un blog :
    http://cocoawithlove.com/2009/10/memory-and-thread-safe-custom-property.html

    On y parle des méthodes accesseurs personnalisées et du "type" atomique ou non. Pas de lien direct avec ton sujet, mais cela complète certainement ton passage sur "atomic"... ou pas.

    Voilà , ça peut vous intéresser également.
  • ClicCoolClicCool Membre
    22:36 modifié #24
    dans 1256541182:

    Salut Ali,

    Tiens, un article vient de tomber sur un blog :
    http://cocoawithlove.com/2009/10/memory-and-thread-safe-custom-property.html

    On y parle des méthodes accesseurs personnalisées et du "type" atomique ou non. Pas de lien direct avec ton sujet, mais cela complète certainement ton passage sur "atomic"... ou pas.

    Voilà , ça peut vous intéresser également.


    Merci Muqaddar :)

    Je découvre l'intérêt des [tt]retain[/tt]/[tt]autorelease[/tt] des properties atomic et j'avoues que, sans le [tt]@synthétize[/tt], j'oublirai souvent de faire ainsi ...
    To maintain atomicity, you also need a retain/autorelease pattern and lock on any getter methods too:
    - (NSString *)someString<br />{<br />&nbsp; &nbsp; @synchronized(self)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; id result = [someString retain];<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; return [result autorelease];<br />}
    

Connectez-vous ou Inscrivez-vous pour répondre.