Copy, dealloc et garbage

TchouboudouTchouboudou Membre
20:47 modifié dans API AppKit #1
Bonsoir les gens.

Aujourd'hui, j'ai ouvert XCode (oOoOo) et j'ai fait des petits testounets. Et j'ai voulu essayer copy. ça marche, mais pour être franc, je vois pas la différence en un copy et un retain :

aString = [string copy] et aString = [string retain] // C'est pas la même chose ?


Aussi, j'ai insérer une méthode dealloc, mais elle n'est pas utilisé (j'y ai mis un NSLog pour voir). Est-ce normal ?

Enfin, comment on utilise le garbage collection d'Objective-C 2.0 (après l'avoir mis en Supported ou Required dans XCode) ?

Merci d'avance,
Tchouboudou

Réponses

  • psychoh13psychoh13 Mothership Developer Membre
    20:47 modifié #2
    Le mode de fonctionnement de -copy dépend de l'objet.
    Par exemple, si ton objet est modifiable comme une NSMutableString, alors -copy créera une nouvelle instance de ta chaà®ne de caractères et la retournera avec un nombre de référence à  1.
    Dans le cas d'une NSString, un objet non-modifiable, copier l'objet ne servirait à  rien, tu ferais un deuxième objet qui n'est pas plus modifiable que le premier, tu ne pourras modifier aucun des deux, alors autant économiser la mémoire et faire un simple retain dessus. C'est ce qu'il se passe avec les NSString.
    Par contre, si la classe implémente le protocole NSMutableCopying, et que tu envoies le message -mutableCopy, là  tu auras bien deux objets différents.
  • AliGatorAliGator Membre, Modérateur
    20:47 modifié #3
    La grande différence dans ce cas là  étant bien sûr que, si tu as 2 variables NSMutableStrings, si tu fais [tt]str2 = [str1 retain];[/tt] cela va pointer sur le même objet, et du coup une modification de str1 impactera str2. Alors que si tu fais [tt]str2 = [str1 copy];[/tt] tu obtiens une nouvelle instance, clone de la première au moment où le "copy" est fait. Mais du coup une modification de str1 ne modifie plus str2, elles sont indépendantes, ce sont 2 instantes différentes.

    Pour ton dealloc, tu l'as bien déclaré comme il faut, avec le "-" et tout ?
  • TchouboudouTchouboudou Membre
    novembre 2007 modifié #4
    Merci pour vos réponses.

    J'ai mis - (void)dealloc comme d'habitude.
  • psychoh13psychoh13 Mothership Developer Membre
    20:47 modifié #5
    Si tu utilises le garbage collector, définis la méthode - (void)finalize et fait un NSLog dedans, normallement tu dois appeler le finalize de la super classe.
  • TchouboudouTchouboudou Membre
    novembre 2007 modifié #6
    Je suis en Objective-C Garbage Collection Unsupported. Voilà  mon code de dealloc :

    - (void)dealloc<br />{<br />	NSLog(@&quot;Test&quot;);<br />	[string release];<br />	[super dealloc];<br />}
    


    C'est bizarre...

    J'ajoute que le programme, c'est juste un test ou j'ai mis une NSString, qui dans l'init, j'ai fait string = [[NSString alloc] initWithString:@Test];

  • psychoh13psychoh13 Mothership Developer Membre
    20:47 modifié #7
    Bon, chez moi, j'ai écris ce code test :

    @interface Test : NSObject<br />{<br />&nbsp; &nbsp; NSString *string;<br />}<br />@end<br /><br />@implementation Test<br />- (id) init<br />{<br />&nbsp; &nbsp; self = [super init];<br />&nbsp; &nbsp; if (self != nil)<br />&nbsp; &nbsp; {<br />&nbsp; &nbsp; &nbsp; &nbsp; string = [[NSString alloc] initWithString:@&quot;Test&quot;];<br />&nbsp; &nbsp; }<br />&nbsp; &nbsp; return self;<br />}<br /><br />- (void) dealloc<br />{<br />&nbsp; &nbsp; NSLog(@&quot;Test&quot;);<br />&nbsp; &nbsp; [string release];<br />&nbsp; &nbsp; [super dealloc];<br />}<br />@end<br /><br />int main (int argc, const char * argv&#91;]) {<br />&nbsp; &nbsp; NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; [[[Test alloc] init] release];<br />&nbsp; &nbsp; <br />&nbsp; &nbsp; [pool drain];<br />&nbsp; &nbsp; return 0;<br />}
    


    Alors comme j'ai pas le reste de ton code je peux pas vraiment dire ce qui cloche.
  • TchouboudouTchouboudou Membre
    20:47 modifié #8
    Tout est pareil, sauf le main.m :

    #import &lt;Cocoa/Cocoa.h&gt;<br /><br />int main(int argc, char *argv&#91;])<br />{<br /> &nbsp; &nbsp;return NSApplicationMain(argc, &nbsp;(const char **) argv);<br />}
    
  • psychoh13psychoh13 Mothership Developer Membre
    novembre 2007 modifié #9
    Pour le main c'est normal... Maintenant, la question piège : est-ce que ton objet est créé ? :D
    Si oui, où ? Et qu'est-ce qui te fait penser qu'il l'est ? Et pour finir, où est-il supprimé et qu'est-ce qui te fait penser qu'il l'est ? :D

    (En simplifiant : montre-nous ton code  ;D)
  • TchouboudouTchouboudou Membre
    20:47 modifié #10
    Il est créé, je fais un NSLog dans le init.
    Par contre, pour la suppression, je sais pas, justement.

    @interface AppController : NSObject {<br />	NSString *string;<br />}<br /><br />@end<br /><br />@implementation AppController<br /><br />- (id)init<br />{<br />	if (self = [super init])<br />	{<br />		string = [[NSString alloc] initWithString:@&quot;Test&quot;];<br />		NSLog(@&quot;%@&quot;, string);<br />	}<br />	return self;<br />}<br /><br />- (void)dealloc<br />{<br />	NSLog(@&quot;%@&quot;, string);<br />	[string release];<br />	[super dealloc];<br />}<br /><br />@end
    
  • psychoh13psychoh13 Mothership Developer Membre
    20:47 modifié #11
    Il doit être supprimé à  la sortie de l'application, c'est pour ça sans doute que ne voit pas le log...
  • TchouboudouTchouboudou Membre
    20:47 modifié #12
    Ha, je veux bien moi, pas de problème. Comment je fais  :)beta: ?

    Aussi, j'ai vu que le main.m était différent, et qu'il ne marquait pas le NSAutoreleasePool. Est-ce qu'il y a un moyen de l'avoir dès la création d'un nouveau projet ?
  • psychoh13psychoh13 Mothership Developer Membre
    20:47 modifié #13
    J'ai pris un projet de Command-line Tool --> Foundation Tool, c'est un projet uniquement en ligne de commande. Dans ton projet de type Cocoa Application tu ne dois jamais toucher à  ton main(), les NSAutoreleasePool sont gérés automatiquement par l'AppKit.

    Sinon pour ton -dealloc, il n'y a rien à  faire, il est supprimé automatiquement quand tu fermes l'application, c'est le seul moment où il a besoin d'être désalloué.
  • TchouboudouTchouboudou Membre
    20:47 modifié #14
    Pourtant, je ferme l'application et rien ne se passe. Alors soit il y a un problème, soit l'application est intelligent, et elle sait quand il reste des variables à  releaser et elle appelle - dealloc quand c'est le cas. Mais ça m'étonnerait sachant que la variable string n'est pas releaser...
  • psychoh13psychoh13 Mothership Developer Membre
    20:47 modifié #15
    De toutes façons lorsque tu fermes l'application le système libère toute la mémoire que tu lui as alloué.
  • TchouboudouTchouboudou Membre
    20:47 modifié #16
    Mais, c'est quand même bizarre que la méthode ne soit pas appelé. Merci en tout cas.
  • psychoh13psychoh13 Mothership Developer Membre
    20:47 modifié #17
    Elle l'est peut-être mais tu ne le vois pas.
  • novembre 2007 modifié #18
    Non, elle ne l'est pas. Une petite lecture de - (void)terminate:(id)sender pour avoir un bout de réponse... quand à  la raison exacte...

    La majorité des applications fonctionnent comme ça alors... non peut être pas besoin de forcer le release puisque ton code est juste... enfin à  mon avis.
Connectez-vous ou Inscrivez-vous pour répondre.