在dealloc方法中发布NSTimer的正确方法是什么?它是用以下代码创建的?
-(void)mainTimerLoop {
mainTimer = [NSTimer scheduledTimerWithTimeInterval:1/10
target:self
selector:@selector(gameLoop)
userInfo:nil
repeats:YES];
}
由于
答案 0 :(得分:16)
你这样做的方式,你永远不会点击dealloc
。计时器保留其目标。在这种情况下,这意味着计时器保留了您。在它失效之前它不会释放你。由于您创建了计时器,因此必须在dealloc
之前的某个时间点使其无效,因为计时器的保留将阻止您的对象被dealloc
编辑。
您有两种选择:
作为后者的一个例子:
@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];
}
请注意时间间隔是1.0/10.0
- 这也可以写成0.1
,但不能写入1/10
,因为该分区将截断为0.0
。
还要注意这会如何打破保留周期:
答案 1 :(得分:1)
运行循环保留有效的NSTimer,如果重复,则将永久保留或直到您使其无效。您不应该释放它,因为在您的示例代码中,您没有明确地保留它。如果你使它无效,它将不再被运行循环保留,并将被自动释放。
对于重复计时器来说这可能没问题,但对于一次性计时器来说是危险的,因为它可能会在您访问它之前释放它以查看它是否有效和/或尝试使其无效(这将导致一个糟糕的访问应用程序崩溃)。因此,如果您计划在创建后查看计时器变量(包括检查它,使其无效和/或释放它),那么在应用程序中的某处显式保留它可能是一个好习惯,然后释放它并在它无效后将其设置为nil并完成它。
如果将其声明为retain属性,则可以在一个语句中释放它并将其设置为nil。然后你可以写:
self.timer = nil;
答案 2 :(得分:-1)
你对这里的NSTimer有一个非常好的答案How do I use NSTimer?那里他们谈到停止重复做NSTimer
[myTimer invalidate];
答案 3 :(得分:-3)
您无需释放它,因为它将自动释放。由便捷方法创建的任何东西(即你不自己调用alloc
)是被调用函数对内存管理的责任,这通常意味着它会在它之前创建的对象上调用autorelease
退货。
我会将计时器分配给具有retain
关键字的属性,但要确保它不会被取消分配给您。通常,如果事件循环中没有任何保留,则会在事件循环中释放自动释放的对象。