2

这个问题已经在堆栈溢出时被问死了,我已经看到了很多答案,但不知何故我仍然遇到了麻烦。

无论如何,我分配了一个 NSTimer,因为在我看来确实加载了:

NSTimer *oneSecondTicker = [[NSTimer alloc] init]; 
oneSecondTicker = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateLabelsWithOneSecondTicker) userInfo:nil repeats:YES]; 
self.dateForTimeLabel = [NSDate date];

作为选择器的方法是:

-(void) updateLabelsWithOneSecondTicker {
    if(self.dateForTimeLabel != nil)  
    {
        self.lblTime.text = [NSString stringWithFormat:@"%f", fabs([self.dateForTimeLabel timeIntervalSinceNow])];
    }
}

这种方法基本上每秒更新一个标签,给我一个计时器/秒表之类的东西。

我还有一个开始/暂停按钮,当按下它暂停时:

[oneSecondTicker invalidate];
oneSecondTicker = nil;

如果按下按钮重新开始,方法是:

NSTimer *oneSecondTicker = [[NSTimer alloc] init];
oneSecondTicker = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateLabelsWithOneSecondTicker) userInfo:nil repeats:YES];    

self.dateForTimeLabel = [NSDate date];

我不给计时器调用保留,它没有属性,也没有合成。然而,它在接口中被声明。

为了解决这个问题,每次按下暂停/开始按钮都会发生什么,计时器不会失效,时间标签会越来越快地更新,让我相信由于某种原因存在多个计时器。(显然,在这些方法中还没有找到真正的计时器的功能,这只是让我的 NSTimer 工作的测试)。

怎么会这样?

4

2 回答 2

11

你写了这个:

NSTimer *oneSecondTicker = [[NSTimer alloc] init];

该行创建了一个局部变量。它不会设置您在界面中声明的属性。oneSecondTicker该行还创建了一个计时器,当您重新分配指向您创建的计时器时,您会立即在下一行中将其销毁scheduledTimerWithTimeInterval:。这是一个初学者错误,表明您需要了解指针的工作原理。

无论如何,您正在使用scheduledTimerWithTimeInterval:.... 这意味着计时器在运行循环中自动调度自身。当一个定时器被安排在一个运行循环中时,运行循环会保留这个定时器。这就是为什么(假设您使用 ARC)即使您发布了对它的引用,计时器仍然存在。

您需要将计时器存储在实例变量中。我假设您使用的是 Xcode 4.4 或更高版本,因此该属性正在自动合成。如果您声明了 like 属性@property (nonatomic, strong) NSTimer *oneSecondTicker,那么您可以像这样创建计时器:

self.oneSecondTicker = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateLabelsWithOneSecondTicker) userInfo:nil repeats:YES]; 

当你想使它失效时,你可以这样说:

[self.oneSecondTicker invalidate];
self.oneSecondTicker = nil;
于 2012-08-25T05:59:39.003 回答
0

您没有保留 timer 变量。

删除这个:

NSTimer *oneSecondTicker = [[NSTimer alloc] init]; 

将您的计时器移至类属性为@property (strong)NSTimer *oneSecondTicker;

用这个:

self.oneSecondTicker = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateLabelsWithOneSecondTicker) userInfo:nil repeats:YES];

重新启动计时器时再次使用 self.oneSecondTicker。

于 2012-08-25T05:59:40.973 回答