16

我有一个带有倒数计时器的应用程序。我已经用这样的方式用从计时器调用的函数更新了一个标签:

...
int timeCount = 300; // Time in seconds
...
NSTimer *myTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(actualizarTiempo:) userInfo:nil repeats:YES];
...
- (void)actualizaTiempo:(NSTimer *)timer {
    timeCount -= 1;
    if (timeCount <= 0) {
        [timer invalidate];
    } else {
        [labelTime setText:[self formatTime:timeCount]];
    }
}

注意:formatTime 是一个接收整数(秒数)并返回格式为 mm:ss 的 NSString 的函数

一切正常,也就是说,时间倒计时,但问题是我在应用程序中有一个 UITableView,如果我触摸表格并拖动它(沿着单元格移动),计时器会停止,直到我从屏幕上松开手指...

这种行为正常吗?如果是,有什么办法可以避免它并在拖动表格时使计时器工作?

4

4 回答 4

31

通过使用scheduledTimerWithTimeInterval:,正如 j.tom.schroeder 所说,您的计时器会自动安排在默认模式的主运行循环上。这将防止你的计时器在你的运行循环处于非默认模式时触发,例如,当点击或滑动时。

但是,解决方案不是使用线程,而是为所有常见模式安排计时器:

NSTimer *timer = [NSTimer timerWithTimeInterval:1
                                         target:self
                                       selector:@selector(actualizarTiempo:)
                                       userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

根据您希望在不停止计时器的情况下允许的事件类型,您也可以考虑UITrackingRunLoopMode. 有关运行循环模式的更多信息,请参阅Apple Docs

于 2012-07-29T20:36:25.433 回答
4

这是 Swift 版本:

斯威夫特 2

var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "removeFromSuperview", userInfo: nil, repeats: false)
NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)

斯威夫特 3, 4, 5

var timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(removeFromSuperview), userInfo: nil, repeats: false)
RunLoop.main.add(timer, forMode: RunLoop.Mode.common)
于 2015-08-20T12:06:11.487 回答
0

这是正常行为。scheduledTimerWithTimeInterval:调度当前运行循环,因此与 UITableView 的任何交互都将阻止actualizarTiempo:调用该方法。使用 NSThread 方法detachNewThreadSelector:toTarget:withObject并在单独的线程上sleepForTimeInterval执行。actualizarTiempo:

于 2012-07-29T20:23:41.053 回答
0

斯威夫特版本 4+:

var timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.TimerController), userInfo: nil, repeats: true)
RunLoop.main.add(timer, forMode: RunLoopMode.commonModes)

如果你想重复例如作为一个计数器然后设置repeat = true else = false

于 2018-10-26T11:03:32.480 回答