这可能会回答您关于NSTimer 实时行为的问题:
定时器不是实时机制;它仅在已添加计时器的运行循环模式之一正在运行并且能够检查计时器的触发时间是否已过时触发。由于典型的运行循环管理的各种输入源,计时器的时间间隔的有效分辨率被限制在 50-100 毫秒的数量级。如果计时器的触发时间发生在长时间调用期间或运行循环处于不监视计时器的模式下,则计时器不会触发,直到运行循环下次检查计时器。因此,定时器触发的实际时间可能是计划触发时间之后的一个重要时间段。
您没有指定如何安排 NSTimer,但如果您安排它NSRunLoopCommonModes
而不是NSRunLoopDefaultModes
:
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
如果这不能改善情况,那么您应该寻找较低级别的替代方案。
特别是,您可能会查看CADisplayLink
:
CADisplayLink 对象是一个计时器对象,它允许您的应用程序将其绘图与显示器的刷新率同步。
它可以以与 NSTimer 非常相似的方式使用。
CADisplayLink 的优势在于它与刷新率相关联,因此它应该在 1/60 秒的时间间隔内提供相当可靠的行为。
CADisplayLink 的使用示例:
CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(respondToTimer)];
[displayLink setFrameInterval:60];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
这将调用respondTimer
每 60 个刷新帧,即每秒一次。由于您希望只调用一个方法,因此可以使用:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC),
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self respondToTimer];
});
这对你来说可能会更容易。(当然,您可以用该方法的完整实现替换对 [self respondToTimer] 的调用)。