我有一个在5秒内触发的计时器被添加到全局队列,虽然我在2秒后使其无效,但是运行循环不会终止直到5秒。在下面的代码片段中,backgroundTimer是一个实例var,而run是一个成员函数。以下代码中阻止运行循环终止的错误。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
_backgroundTimer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(run) userInfo:nil repeats:NO];
[ [NSRunLoop currentRunLoop] addTimer:_backgroundTimer forMode:NSRunLoopCommonModes];
[[NSRunLoop currentRunLoop] run];
NSLog(@"Run loop terminated");
});
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[_backgroundTimer invalidate];
_backgroundTimer=nil;
});
答案 0 :(得分:3)
这里的第一个问题是你的计时器被添加到某个任意后台线程的运行循环中。 (即线程将由GCD创建以服务后台队列)你可以这样做,但它没有任何意义。
除此之外,你说你想要发生的是这个运行循环退出,但在-run
方法的文档中,它说如下:
从运行循环中手动删除所有已知输入源和计时器 不保证运行循环将退出。 OS X可以安装和 根据需要删除其他输入源以处理目标请求 在接收者的线程。因此,这些来源可以阻止这些 从退出中运行循环。
如果您希望运行循环终止,则不应使用此方法。 相反,使用其他运行方法之一,并检查其他方法 你自己的任意条件,循环。
如果要在计时器无效时退出事件循环,则需要自行旋转事件循环。例如:
while (_backgroundTimer.valid && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]]);
这将在定时器失效后最多退出运行循环0.1( - epsilon)秒。
答案 1 :(得分:0)
试试这样:
[NSRunLoop cancelPreviousPerformRequestsWithTarget:self selector:@selector(run) object:nil];
<强>编辑:强>
-(void)run{
if(taskComplete){
[_backgroundtimer invalidate];
}