这个问题已经被要求在堆栈溢出时死亡,我已经看到了过多的答案,但不知怎的,我仍然遇到麻烦。
无论如何,我在我的视图中分配了一个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];
我没有对计时器调用retain,它没有属性,也没有合成。然而,它在界面中声明。
为了解决这个问题,按下每个暂停/开始按钮会发生什么,定时器不会失效,时间标签会更快更快地更新,这让我相信多个定时器由于某种原因而存在。 (显然,在这些方法中还没有找到真正计时器的功能,这只是让我的NSTimer工作的一个测试。)
这怎么可能?
答案 0 :(得分:12)
你写了这个:
NSTimer *oneSecondTicker = [[NSTimer alloc] init];
该行创建本地变量。它不设置您在界面中声明的属性。该行还会创建一个计时器,当您重新指定oneSecondTicker
以指向使用scheduledTimerWithTimeInterval:
创建的计时器时,您会在下一行中立即销毁该计时器。这是一个初学者错误,表明您需要了解指针的工作原理。
无论如何,您正在使用scheduledTimerWithTimeInterval:...
创建计时器。这意味着计时器在运行循环中自动调度自身。在运行循环中调度计时器时,运行循环会保留计时器。这就是为什么(假设你正在使用ARC),即使你发布了对它的引用,计时器依然存在。
您需要将计时器存储在实例变量中。我假设您使用的是Xcode 4.4或更高版本,因此该属性正在自动合成。如果您将属性声明为@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;
答案 1 :(得分:0)
您没有保留计时器变量。
删除它:
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。