正确发布NSTimer的方法?

时间:2010-10-19 18:58:52

标签: iphone objective-c nstimer

在dealloc方法中发布NSTimer的正确方法是什么?它是用以下代码创建的?

-(void)mainTimerLoop {

     mainTimer = [NSTimer scheduledTimerWithTimeInterval:1/10
                                                  target:self 
                                                selector:@selector(gameLoop) 
                                                userInfo:nil
                                                 repeats:YES];
}

由于

4 个答案:

答案 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

还要注意这会如何打破保留周期:

  • 您和您的计时器都保留计时器目标。
  • 你在正常时间点击了dealloc。
  • 然后使计时器无效并释放计时器目标。
  • 然后取消分配计时器目标。

答案 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关键字的属性,但要确保它不会被取消分配给您。通常,如果事件循环中没有任何保留,则会在事件循环中释放自动释放的对象。