麻烦使用arc-IOS使NSTimer无效

sta*_*lew 2 nstimer ios

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

无论如何,我在我的视图中分配了一个NSTimer,所以加载:

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

选择器的方法是:

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

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

我还有一个开始/暂停按钮,当按下暂停时会执行以下操作:

[oneSecondTicker invalidate];
oneSecondTicker = nil;
Run Code Online (Sandbox Code Playgroud)

如果按下按钮再次启动,方法是:

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

self.dateForTimeLabel = [NSDate date];
Run Code Online (Sandbox Code Playgroud)

我没有调用保留到计时器,它没有属性,也没有合成.然而,它在界面中声明.

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

怎么会这样?

rob*_*off 11

你写了这个:

NSTimer *oneSecondTicker = [[NSTimer alloc] init];
Run Code Online (Sandbox Code Playgroud)

该行创建一个局部变量.它并没有设置您在接口中声明的属性.该行还会创建一个计时器,当您重新分配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]; 
Run Code Online (Sandbox Code Playgroud)

当你想要无效时,你可以这样说:

[self.oneSecondTicker invalidate];
self.oneSecondTicker = nil;
Run Code Online (Sandbox Code Playgroud)