Gestion de la mémoire et variables d'instance
chaps31
Membre
Bonjour à tous,
Bon, visiblement je n'ai pas tout compris.. Si, si je vous assure... :P
Mon problème :
Soit une classe avec un awakefromnib dans lequel entre autre j'initialise des variables d'instance de cette classe.
J'ai une variable d'instance NSMutableString maVar.
Une action de l'utilisateur lui donne une valeur avec un setString:
Nouvelle action de l'utilisateur (donc appel à une autre méthode) et là maVar est vide.... ben c'est une variable d'instance de ma classe bon sang...
J'imagine que je m'emmêle encore dans la gestion de la mémoire... J'ai lu qu'il faut à chaque fois que l'on attribue une valeur à une variable d'instance faire un retain, ce que je n'avais pas fait. Je pensais que ça venait de là donc j'ai rajouté un retain sur la variable utilisée comme argument du setString:
Ben non, ça marche pas ma variable d'instance une fois la méthode terminée revient à "vide".
SOS, merci...
NB : Question subsidiaire, j'imagine que lorsque l'on change la valeur d'une variable d'instance, comme on fait un retain à chaque fois il faut faire un release juste avant. Je ne l'ai pas fais en l'occurence pour le test.
Bon, visiblement je n'ai pas tout compris.. Si, si je vous assure... :P
Mon problème :
Soit une classe avec un awakefromnib dans lequel entre autre j'initialise des variables d'instance de cette classe.
J'ai une variable d'instance NSMutableString maVar.
Une action de l'utilisateur lui donne une valeur avec un setString:
Nouvelle action de l'utilisateur (donc appel à une autre méthode) et là maVar est vide.... ben c'est une variable d'instance de ma classe bon sang...
J'imagine que je m'emmêle encore dans la gestion de la mémoire... J'ai lu qu'il faut à chaque fois que l'on attribue une valeur à une variable d'instance faire un retain, ce que je n'avais pas fait. Je pensais que ça venait de là donc j'ai rajouté un retain sur la variable utilisée comme argument du setString:
Ben non, ça marche pas ma variable d'instance une fois la méthode terminée revient à "vide".
SOS, merci...
NB : Question subsidiaire, j'imagine que lorsque l'on change la valeur d'une variable d'instance, comme on fait un retain à chaque fois il faut faire un release juste avant. Je ne l'ai pas fais en l'occurence pour le test.
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Non pas forcément. ça dépend si ta classe veut seulement garder une référence vers l'objet ou également s'assurer qu'il ne va pas être désalloué.
C'est la différence entre (assign) et (retain) pour les propriétés. Mais il est vrai que c'est ce qu'on fera le plus souvent.
Oui, exactement.
J'ai commencé une série d'articles sur la gestion mémoire. Les prochaines épisodes arrivent bientôt.
Si tu as une méthode setString dans une classe, d'après les conventions de nommage, elle est sensée faire elle même le retain de la nouvelle chaà®ne et le release de l'ancienne. Donc si tu utilises [tt][maVar setString:s][/tt] tu n'as pas à faire le retain sur s et le release sur l'ancienne valeur de maVar, setString le fait tout seul. C'est à ça que servent les méthodes setter d'ailleurs, entre autres.
C'est si tu faisais [tt]maVar = s[tt/] que là il y aurait un problème de mémoire (il faudrait faire un retain de s d'abord, un release de maVar ensuite pour releaser l'ancienne valeur, et seulement enfin affecter s à maVar... mais bon c'est précisément ce que fait un setter justement)
Sinon qu'entends-tu par "maVar est vide" ? elle est égale à une chaà®ne vide, ou elle est égale à nil ?
Un extrait du code concernant ta question aiderait à y voir plus clair.
Faut juste muter son contenu aux changement de valeur.
Par contre à son initialisation première faut un retain, et dans le dealloc un release.
Après, on peut se poser la question de la pertinence du choix d'un mutable pour une string et de l'encapsulation necessaire pour s'assurer qu'elle soit pas modifiée indument ailleurs que dans le setter.
Le Getter pourrait par exemple ne renvoyer qu'une copie non mutable de la variable ... ?
Avec cette base je vais chercher si vraiment je continue de sécher je reviens, histoire d'éviter de trop faire de flood...
Je trouvais ça bizarre, et puis je me suis dis que la variable d'instance continue d'exister après la fin de la méthode, alors que la variable interne à la méthode non, ainsi la variable d'instance pointera sur un espace mémoire désalloué.
Sauf si on utilise un setter qui fait tout seul un retain, donc pas besoin, j'ai compris ? Merci
pour le retain c'est en effet normal qu'il faille le faire dans le cas que tu décris car en effet ta variable interne à la méthode (variable locale, quoi) va justement devenir "out of scope" une fois que tu seras sorti de ta méthode, alors que la variable d'instance elle pourra être accédée hors de cette méthode.
Par contre, avant d'affecter cette variable d'instance, qui contiendra toujours un objet qui sera "retain" justement par cette variable d'instance (puisque par principe elle est accessible tout le temps où la classe qui la contient existe), il faut penser à faire un "release" sur l'ancienne valeur contenue dans cette variable d'instance. Pour équilibrer les appels retain/release sur les objets.
Et en effet si tu passes par un setter, tout ça est fait tout seul, puisque le setter se charge de relâcher (release) l'ancienne valeur de la variable et de retenir (retain) la nouvelle.
(De même, il faudra faire un release sur la variable d'instance, si elle a été affectée, quand l'objet qui la contient est détruit, mais ça ça se fait dans le dealloc et normalement tu l'as déjà codé)
Juste pour le plaisir de pinailler, je dirais ici le temps où l'instance de la classe qui la contient existe
[EDIT] zut, 2 min trop tot !!!
Personnellement, je te conseille d'utiliser une simple NSString, et quand tu changes sa valeur tu fais un release de l'ancienne valeur et une copie de la nouvelle valeur.
Avec ce code, si la valeur retournée par [identField stringValue] est une chaà®ne de caractères non-modifiable, envoyer le message -copy ne fera rien de plus qu'un retain, en revanche, si l'objet est modifiable (NSMutableString) il créera une nouvelle instance non-modifiable de cet objet.