[1/2 résolu]releaser proprement
bonsoir et joyeuses fetes,
comment releaser vous un objet qui est retenu par ses propres property ?
ex
la soluce a deux methodes est peu sastifaisante
invalidateKeepAlive puis release
ou surcharger release
mais release va etre appelé deux fois (meme pas sur que cela soit propre comme code
)
bref comment faites vous?
comment releaser vous un objet qui est retenu par ses propres property ?
ex
<br />@interface BC_Zoo : NSObject <NSStreamDelegate> {<br /> .../... <br /> NSTimer *keepAlive;<br /> .../...<br />}<br /><br />.../...<br /><br />- (id)initWith....<br />{<br /> [super init];<br /> if (self) {<br /><br /> .../... <br /> keepAlive = [[NSTimer scheduledTimerWithTimeInterval:15<br /> target:self<br /> selector:@selector(keepAlive)<br /> userInfo:nil<br /> repeats:YES]retain];<br /> }<br /> <br /> return self;<br />}<br /><br />
la soluce a deux methodes est peu sastifaisante
invalidateKeepAlive puis release
ou surcharger release
<br />- (void)release<br />{<br /> NSLog(@"invalide le timer");<br /> <br /> [keepAlive invalidate];<br /> <br /> [super release];<br />}<br />
mais release va etre appelé deux fois (meme pas sur que cela soit propre comme code

bref comment faites vous?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Si tu n'as pas créé ton timer via alloc copy ni appliqué de retain (ce qui est le cas ici) tu n'as pas à te soucier du release. En plus je connais la méthode - (void)dealloc mais pas cette release que tu as codée.
Si tu fais un retain via les properties tu dois faire un release dans le dealloc mais ici tu ne sembles pas les utiliser sinon tu aurais écrit self.keepAlive = ..
il ne m'est pas possible de releaser simplement car le timer retient lui meme l'objet (cycle).
a) il faut que j'invalide le timer (== il relache l'objet)
b) que je release l'objet, qui releasera le timer.
voila ca fonctionne, mais peut t'on faire plus simple?
car je dois faire
[objet invalidateTimers];
[objet release];
un simple
[objet release] semble plus naturel ?
Sauf que tel que tu l'as écris, ça ne marchera pas, puisque, en imaginant par exemple tu appelles 2 fois retain sur cet objet, au premier release le timer sera invalidé, alors que l'objet, lui, ne sera pas détruit (puisque "retain count" de 1).
D'une manière générale, il est fortement déconseillé de surcharger les méthodes de gestion mémoire. Alors certes, il faut invalider le timer "à la main", mais c'est la façon de faire prônée par Apple.
Moi ce que je ferais c'est que je ne ferai pas de "retain" sur le timer car dès que tu le schedule sur la RunLoop elle retient le Timer elle-même (voir le Programming Guide" sur les timers tout est expliqué comme d'hab) et dans le dealloc tu le invalidate (et la runloop qui le retenait va le releaser)
En tout cas surtout pas surcharger la méthode "release" !!! S'il te vient l'idée de faire une chose pareille c'est que tu n'as pas lu assez de tutos sur la gestion mémoire !!
non, un simple release suffit
ma surchage de "release" s'auto-appele lors de [timer invalidate], bon je te l'accorde ca ne me plais pas.
et pas sur que cela soit correcte, meme si ca fonctionne.
je vais lire, mais pas de retain == mon timer est releaser
j'ai opté pour la soluce avec les 2 methodes.
merci ali, c'est resolu
un peu vite
le problème est le même, le timer possède tjrs une ref sur l'objet (pour le "tarjet", je pense), donc mettre invalidate dans le dealloc ne sert a rien.
il faut deux methodes.....
Je ne vois pas trop ce qui pose problème dans ton cas du coup.
Le "init" sur ton objet n'est appelé qu'à la création de l'objet, pas à chaque "retain" sur ledit objet ; le "dealloc" sur ton objet est automatiquement appelé quand l'objet est détruit (tu n'appeles jamais le dealloc directement, surtout pas !) parce que son retainCount tombe à zéro,et pas à chaque release. Bref en mettant le "scheduledTimer..." dans le init il ne sera bien créé et programmé qu'à la création, et en mettant le "invalidate" dans le dealloc il ne sera bien détruit qu'à la destruction de ton objet. Et entre temps si tu fais des retain et release sur ton objet tu n'as pas à toucher ton NSTimer, il sera toujours retenu par ton objet tant que l'objet ne sera pas détruit...
Bref un cas classique de composition (au sens conception/architecture/UML). C'est vrai pour les NSTimer comme pour le reste d'ailleurs...
voila mon init
donc keepAlive est une simple assignation, il n'y a aucun retain "explicite" sur le timer, il est retenu par la runLoop.
il ne faut pas se fier au retainCount aveuglement, mais a la sortie de mon init il est egal a 2.
si je commente le timer il est egale a 1.
donc mettre [keepAlive invalidate] dans dealloc ne sert a rien, dealloc ne sera pas appelé (retainCount -1 = 1) et non 0.
je pense que le timer retient son "target".
faites l'essai bon sang. ;-)
Stops the receiver from ever firing again and requests its removal from its run loop.
- (void)invalidate
Discussion
This method is the only way to remove a timer from an NSRunLoop object. The NSRunLoop object removes and releases the timer, either just before the invalidate method returns or at some later point.
ICI +++> If it was configured with target and user info objects, the receiver releases its references to those objects as well.
Special Considerations
You must send this message from the thread on which the timer was installed. If you send this message from another thread, the input source associated with the timer may not be removed from its run loop, which could prevent the thread from exiting properly.
Availability
Available in Mac OS X v10.0 and later.
pourquoi pas? (ce n'est pas un troll)
Tu installes deux fois le même timer !
soit tu fais ça:
ou bien ça:
mais pas les deux à la fois ...
C'est dangereux de faire ça !
Pour moi, la meilleur solution est d'utiliser un objet intermédiaire comme target, et faire dans celui-ci un appel sur l'objet initial (BC_Zoo)
ainsi dans le dealloc de BC_Zoo faire:
hein......
qui retient le timer, il faut un retain.
je fais ca non? le timer est retenu par la runLoop et je conserve une reference (pointeur) dessus.
oui, ali m'a fourni une reponse:
mon release est a usage unique, puisque il invalide mon timer, deduit de ...
la SEULE solution propre est la soluce des deux methodes.
merci a vous
Par rapport à toi , dans mon exemple timer est remplacé par TimerWrapper
et BC_Zoo par Counter
Un appui sur le bouton démarre/stoppe le compteur
[counter release] invalide le timer dans dealloc, donc uniquement si Counter est désalloué,
c'est à dire proprement