在dispatch_async中使NSTimer无效

时间:2013-04-18 04:27:02

标签: ios objective-c objective-c-blocks nstimer

我正在创造一个游戏,在游戏中我需要一个时间计数器。

我工作得很好但是当我滚动地图时它停止然后当我完成滚动它再次开始。我用dispatch_async解决了这个问题。这是代码

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

                timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self  selector:@selector(timeNext) userInfo:nil repeats:NO];

                [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

                [[NSRunLoop currentRunLoop] run]; 
            });

计时器:

__block NSTimer *timer;

但是如果应用程序进入后台,我需要停止这个时间(当它变为活动状态时再次启动)。

通过这种方式我可以滚动地图,计时器运行良好我尝试:

- (void)timeNext {
    [timer invalidate];
    }

并且不起作用。谁知道如何阻止它?或任何其他想法来完成这项任务?

3 个答案:

答案 0 :(得分:4)

不要在全局队列的线程上创建计时器,然后在该线程上启动运行循环。

只需在主线程(主运行循环)上创建计时器,并将其添加到跟踪运行循环模式。可以将计时器添加到多个运行循环模式。

timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self  selector:@selector(timeNext) userInfo:nil repeats:NO];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

答案 1 :(得分:1)

如果您正在使用UIScrollView滚动浏览游戏世界,则在滚动跟踪触摸时计时器将暂停 - 您需要设置计时器以使用不同的模式 - UITrackingRunLoopMode,例如

[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

而不是

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

这将允许您的计时器触发事件​​,而滚动等控件正在跟踪用户的触摸。

[编辑]

您可以创建计时器,例如通过

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;

然后将此计时器添加到runloop(基本上,您应该将其添加到您的应用程序主runloop):

NSTimer* timer = [NSTimer timerWithTimeInterval:1./60. target:self selector:@selector(tick) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];

答案 2 :(得分:0)

我使用NSRunLoopCommonModes代替UITrackingRunLoopMode,每个人看起来都很好。主线程ui操作不再阻止tick函数。

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