La façon dont vous le faites, vous ne serez jamais touché dealloc
. Une minuterie conserve sa cible. Dans ce cas, cela signifie que la minuterie vous a retenu. Il ne vous libèrera pas avant d'être invalidé. Depuis que vous avez créé le minuteur, vous devez également l'invalider à un certain moment avant dealloc
, car la fonction de temporisation empêchera l'objet d'être dealloc
.
Vous avez deux options:
- trouver un autre endroit pour invalider la minuterie (vue se offscreen, l'application se termine, ce que vous avez)
- ensemble quelque chose d'autre que l'objectif de la minuterie.
À titre d'exemple de ce dernier:
@interface GameLoopTimerTarget : NSObject {
id owner; /* not retained! */
}
- (id)initWithOwner:(id)owner;
- (void)timerDidFire:(NSTimer *)t;
@end
@implementation GameLoopTimerTarget
- (id)initWithOwner:(id)owner_ {
self = [super init];
if (!self) return nil;
owner = owner_;
return self;
}
- (void)timerDidFire:(NSTimer *)t {
#pragma unused (t)
[owner performSelector:@selector(gameLoop)];
}
@end
/* In your main object… */
/* assume synthesized:
@property (retain, NS_NONATOMIC_IPHONE_ONLY) GameLoopTimer *mainTimerTarget; */
- (void)mainTimerLoop {
self.mainTimerTarget = [[[GameLoopTimerTarget alloc] initWithOwner:self] autorelease];
mainTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0 target:self.mainTimerTarget selector:@selector(timerDidFire:) userInfo:nil repeats:YES];
}
- (void)dealloc {
/* other stuff */
[timer invalidate], timer = nil;
[mainTimerTarget release], mainTimerTarget = nil;
/* more stuff */
[super dealloc];
}
Remarquez comment l'intervalle de temps est 1.0/10.0
- cela pourrait aussi être écrit 0.1
, mais il ne peut pas être écrit 1/10
, comme cette division va tronquer 0.0
.
Notez également comment cela brise le cycle de conserver:
- Vous et votre minuterie la cible de conserver la minuterie.
- Vous avez cliqué sur dealloc à l'heure normale.
- Vous invalidez alors le temporisateur et relâchez la temporisation.
- La cible du temporisateur est ensuite désallouée.
C'est faux - et c'est un très mauvais conseil! La gestion de la mémoire avec un NSTimer est très particulière: elle conserve la cible et ne la libère pas tant qu'elle n'est pas invalidée. S'il crée un NSTimer répétitif avec self comme cible, par conséquent, le temporisateur retient self et donc le dealloc ne sera pas appelé avant * que * le timer ne soit invalidé. Donc ne dites pas "arrêtez le timer * dans * votre méthode dealloc". L'astuce consiste à trouver un endroit pour arrêter le timer * avant * la méthode dealloc. – matt
Down-voté pour les mêmes raisons que données par matt. Besoin d'invalider et de libérer une minuterie en dehors de dealloc. – theLastNightTrain