的[NSTimer scheduledTimerWithTimeInterval:...]
保留目標,因此,如果目標是自我,那麼你的模型類的實例將永遠不會被釋放。
作爲解決方法,可以使用單獨的對象(在以下示例中稱爲TimerTarget
)。 TimerTarget
有一個弱參考ModelClass
,以避免保留週期。
這個「助手類」看起來像這樣。它唯一的目的是將定時器事件轉發給「真實目標」。現在
@interface TimerTarget : NSObject
@property(weak, nonatomic) id realTarget;
@end
@implementation TimerTarget
- (void)timerFired:(NSTimer*)theTimer
{
[self.realTarget performSelector:@selector(timerFired:) withObject:theTimer];
}
@end
,在你的模型類,你可以在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
因此,我們必須
modelInstance ===> timer ===> timerTarget ---> modelInstance
(===> : strong reference, ---> : weak reference)
注意,沒有(強)從定時器引用模型類的實例。
我已用下面的代碼,其5秒後的創建和ModelClass
釋放它的一個實例測試此:
__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;
});
輸出:
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
我從來沒有真正使用過這...當我在學習Objective-C,我總是告訴'dealloc'很少使用了。我的屬性在'dealloc'方法中仍然有效嗎? – Nosrettap
dealloc怎麼樣?是的,他們會。我將它打成答案。 –
酷!如果您將此作爲答案發布,我會接受它 – Nosrettap