麻烦使用arc-IOS使NSTimer无效

时间:2012-08-25 05:46:48

标签: ios nstimer

这个问题已经被要求在堆栈溢出时死亡,我已经看到了过多的答案,但不知怎的,我仍然遇到麻烦。

无论如何,我在我的视图中分配了一个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工作的一个测试。)

这怎么可能?

2 个答案:

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