The [NSTimer scheduledTimerWithTimeInterval:...]
zachowuje cel, więc jeśli cel jest własnym, wówczas instancja klasy modelu nigdy nie będą zwalniane.
Jako obejście można użyć oddzielnego obiektu (w poniższym przykładzie nazwanego TimerTarget
). TimerTarget
ma słabe oznaczenie dla jako odniesienie do ModelClass
, aby uniknąć cyklu zatrzymania.
Ta "klasa pomocnika" wygląda tak. Jego jedynym celem jest przekazanie zdarzenia licznika czasu do "rzeczywistego celu".
@interface TimerTarget : NSObject
@property(weak, nonatomic) id realTarget;
@end
@implementation TimerTarget
- (void)timerFired:(NSTimer*)theTimer
{
[self.realTarget performSelector:@selector(timerFired:) withObject:theTimer];
}
@end
Teraz, w swojej klasie modelu, można utworzyć timera i unieważnia go w 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
Więc mamy
modelInstance ===> timer ===> timerTarget ---> modelInstance
(===> : strong reference, ---> : weak reference)
pamiętać, że nie ma (silny) odniesienie z timera do instancji klasy modelu już.
ja testowałem to z następującego kodu, który tworzy instancję ModelClass
i uwalnia go po 5 sekundach:
__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;
});
wyjściowa:
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
Nigdy naprawdę użył tego wcześniej ... Kiedy uczyłem Objective-C Zawsze byłem powiedział, że 'dealloc' rzadko już używane. Czy moje właściwości będą nadal ważne w metodzie "dealloc"? – Nosrettap
Co powiesz na dealloc? Tak, będą. Piszę to jako odpowiedź. –
Fajnie! Jeśli opublikujesz to jako odpowiedź, zaakceptuję to. – Nosrettap