El [NSTimer scheduledTimerWithTimeInterval:...]
conserve la cible donc si la cible est self alors votre instance de la classe modèle ne sera jamais désallouée.
Comme solution de contournement, on peut utiliser un objet séparé (appelé TimerTarget
dans l'exemple suivant). TimerTarget
a un faible référence à ModelClass
pour éviter un cycle de rétention.
Cette "classe d'aide" ressemble à ceci. Son seul but est de transmettre l'événement du timer à la "vraie cible".
@interface TimerTarget : NSObject
@property(weak, nonatomic) id realTarget;
@end
@implementation TimerTarget
- (void)timerFired:(NSTimer*)theTimer
{
[self.realTarget performSelector:@selector(timerFired:) withObject:theTimer];
}
@end
Maintenant, dans votre classe modèle, vous pouvez créer une minuterie et l'invalider en dealloc
:
@interface ModelClass ()
@property(strong, nonatomic) NSTimer *timer;
@end
@implementation ModelClass
- (id)init
{
self = [super init];
if (self) {
TimerTarget *timerTarget = [[TimerTarget alloc] init];
timerTarget.realTarget = self;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1
target:timerTarget
selector:@selector(timerFired:)
userInfo:nil repeats:YES];
}
return self;
}
- (void)dealloc
{
[self.timer invalidate]; // This releases the TimerTarget as well!
NSLog(@"ModelClass dealloc");
}
- (void)timerFired:(NSTimer*)theTimer
{
NSLog(@"Timer fired");
}
@end
Nous avons donc
modelInstance ===> timer ===> timerTarget ---> modelInstance
(===> : strong reference, ---> : weak reference)
Notez qu'il n'y a plus de référence (forte) de la minuterie à l'instance de la classe modèle.
J'ai testé cela avec le code suivant, qui crée une instance de ModelClass
et le relâche après 5 secondes :
__block ModelClass *modelInstance = [[ModelClass alloc] init];
int64_t delayInSeconds = 5.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
modelInstance = nil;
});
Sortie :
2013-01-23 23:54:11.483 timertest[16576:c07] Timer fired
2013-01-23 23:54:12.483 timertest[16576:c07] Timer fired
2013-01-23 23:54:13.483 timertest[16576:c07] Timer fired
2013-01-23 23:54:14.483 timertest[16576:c07] Timer fired
2013-01-23 23:54:15.483 timertest[16576:c07] Timer fired
2013-01-23 23:54:15.484 timertest[16576:c07] ModelClass dealloc