24

我的应用程序即将完成,Beta 测试在秒表部分发现了一个错误......秒表使用 nstimer 进行计数并有一个用于存储圈数的表,但是当圈表滚动时,手表会停止或暂停并且不弥补失去的时间。

通过使用以下方法消除了这种停滞:

startingTime = [[NSDate date] timeIntervalSince1970];

计算经过的时间。

但我仍然使用 NSTimer 每 0.1 秒触发一次,这意味着即使经过的时间最终会正确更新,滚动仍然会停止计时器......并将其与 Apple 秒表进行比较让我想知道是否秒表有一个单独的线程,仅用于计算经过的时间。有谁知道这是怎么做的?

现在,使用 Epoch 以来的时间在某种意义上运行良好,但它使启动、停止和重新启动秒表的事情变得复杂

当手表停止时,时间被存储并用于计算手表重新启动时的偏移量,但是似乎引入了一些延迟,并且当手表重新启动时时间明显提前。

任何对根本原因或解决方案的想法将不胜感激。

4

2 回答 2

48

bbum 的回答提供了一种更好的方式来设计你的应用程序,但是如果你想让你的计时器无论用户是否在操作 UI 都可以触发,你需要将它添加到 runloop 的跟踪模式中。

假设您正在为 iPhone 开发,该模式是UITrackingRunLoopMode. 如果您正在为 Mac 开发,则有一个类似命名的NSEventTrackingRunLoopMode.

NSRunLoop *runloop = [NSRunLoop currentRunLoop];
NSTimer *timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(myTimerAction:) userInfo:nil repeats:YES];
[runloop addTimer:timer forMode:NSRunLoopCommonModes];
[runloop addTimer:timer forMode:UITrackingRunLoopMode];
于 2010-01-04T01:03:51.587 回答
22

如果事件循环没有运行,任何计时器都不会触发,直到事件循环可以再次运行。即使事件循环没有被阻塞,定时器也不能保证完全按照其配置的时间间隔触发。如果你的时间完全基于定时器触发,错误的数量会随着时间的推移而增加。

您需要与计时器的触发分开跟踪持续时间。每次计时器触发时,重新计算您的持续时间并重新显示。

对于启动/暂停/重启/停止类型的设置,您通常希望:

  • 在开始时获取时间(作为 NSDate 实例或作为 NSTimeInterval 值)

  • 在暂停或停止时,在暂停/停止时抓住时间。从这个时间减去开始时间,你就有了间隔的持续时间

  • 重新启动时,在重新启动时抓住时间,但也要保持已经过去的持续时间

  • 在暂停/停止时,获取暂停/停止的时间并添加已经过去的持续时间

一般来说,使用 NSTimeInterval 值(只是双精度值)来完成所有这些操作是最简单的。但是,如果您需要跟踪事件发生的实际时刻,请改用 NSDate 实例。

于 2010-01-03T18:48:28.783 回答