Doit on toujours utiliser retain pour le paramètre d'une methode ?

zenxzenx Membre
15:20 modifié dans API AppKit #1
Bonjour !

Ma question est certainement mal formuler. En fait, je fais reférence à  un exemple de code que j'ai vu. Celui-ci ressemblait vaguement à  cela :

- (NSDate *)setEntryDate:(NSMutableArray *)date {
 
  [date retain]
  ...

}

Pourquoi a-ton besoin d'incrémenter date ?. Faut il le faire pour chaque argument de chaque methode lorsque l'argument est de type objet ?

Merci.  ;)

Réponses

  • MalaMala Membre, Modérateur
    15:20 modifié #2
    Il faudrait voir le code dans son intégralité mais pour moi cela n'a d'intérêt que si l'on désire conserver une trace de 'date' au niveau de la classe (ex: on l'affecte à  une variable de la classe pour réutiliser cette information par la ensuite une fois sorti de la méthode).

    Dans le cas contraire, le code marchera mais on va tout droit vers une fuite mémoire à  mon avis.
  • AliGatorAliGator Membre, Modérateur
    15:20 modifié #3
    Ce n'est en effet largement pas utile.
    C'est même à  se demander pourquoi cette ligne est présente dans le code. Elle a sûrement une bonne raison, mais cette dernière n'est sûrement pas "parce qu'il faut le faire à  chaque fois" ;)
    Tu n'as pas à  faire de "retain" sur les arguments de tes méthodes, sauf si tu as besoin de cet argument une fois sorti de ta méthode, parce que tu auras stoqué cet argument dans une variable d'instance NSDate* de ta classe par exemple, et donc pour éviter de le perdre lorsque tu sortiras de ta fonction.

    En effet imagine ce genre de cas (MaClasse est une classe perso qui contient une variable d'instance "NSDate* _laDate", pour l'exemple)
    <br />// dans le code de MaClasse :<br />- (void) setDate:(NSDate*)laDate<br />{<br />&nbsp; _laDate = laDate; // si je fais juste ça, dès que la date recevra un release,<br />&nbsp; // elle sera effacée de toute zone mémoire. Donc il faut que je fasse un :<br />&nbsp; [_laDate retain]; // pour en quelque sorte déclarer que j&#39;ai besoin d&#39;elle et que<br />&nbsp; // si une autre variable qui pointait sur cette date (comme celle utilisée lors de l&#39;appel) <br />&nbsp; // reçoit un release, la date reste en zone mémoire pour la var d&#39;instance _laDate<br />}<br />- (NSDate*) getDate<br />{ return _laDate; }<br /><br />// ------------<br />// et dans le &quot;code principal&quot; autre part :<br />- (void)testAppel<br />&nbsp; NSDate* d = [[NSDate alloc] init]; // date du jour<br />&nbsp; MaClasse* c = [[MaClasse alloc] init];<br />&nbsp; [c setDate:d]; // appel de la fonction<br />&nbsp; [d release]; // et hop on libère la date qu&#39;on avait alloué. la date d n&#39;existe plus<br /><br />&nbsp; // du coup si on avais pas fait le retain dans la fonction defineDate,<br />&nbsp; // l&#39;objet date aurait été rayé de la mémoire car plus personne n&#39;avait déclaré<br />&nbsp; // avoir besoin de lui (le retainCount aurait atteint zéro), donc la variable <br />&nbsp; // d&#39;instance _laDate de MaClasse aurait pointé sur un objet inexistant, donc<br />&nbsp; // risque de plantage si on essaye d&#39;y accéder (accès à  une zone mémoire qui<br />&nbsp; // ne pointe sur plus rien)<br /><br />&nbsp; NSDate* d2 = [c getDate]; // si la date a été détruite avant, alors plantage<br />&nbsp; // mais comme on a fait le retain, le &quot;[d release]&quot; au dessus a relâché la variable d,<br />&nbsp; // mais la date est toujours en mémoire : elle n&#39;est plus accessible via la variable d,<br />&nbsp; // mais elle doit encore exister en mémoire pour la variable _laDate ;)<br />
    
  • AliGatorAliGator Membre, Modérateur
    15:20 modifié #4
    Oh, et à  noter aussi que le retain n'est donc à  faire que si tu assignes ton paramètre à  une variable (autre qu'une variable temporaire déclarée dans le corps de ta fonction) par exemple en particulier une variable d'instance. Une assignation avec un "=" je veux dire.
    Mais que si tu stoques la valeur de ton paramètre dans un tableau (NSArray), la méthode "setValue:forKey:" de la classe NSArray fait toute seule le retain nécessaire.

    Enfin donc c'est uniquement quand tu fais un "maVariableDInstance = monParametre" que tu dois faire un retain dessus pour déclarer "attention je référence mon objet à  un endroit supplémentaire", donc quand tu feras un "release" pour déclarer "il y a une variable de moins qui pointe sur cet objet", tu équilibreras les comptes.

    Le sujet de la gestion de la mémoire était assez particulier en Objective-C (pas forcément simple à  comprendre de prime abord, mais dès qu'on a eu le déclic c'est bon), je te conseille vivement de lire les articles traitant de la gestion de la mémoire avant de poursuivre ;)
Connectez-vous ou Inscrivez-vous pour répondre.