[英]Timer inside global queue is not calling in iOS
-(void)viewDidLoad{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[NSTimer scheduledTimerWithTimeInterval:0.10
target:self
selector:@selector(action_Timer)
userInfo:nil
repeats:YES];
}
);
}
-(void)action_Timer{
LOG("Timer called");
}
没有调用action_Timer
。 我不知道为什么。 你有什么主意吗?
您正在从GCD工作线程调用+[NSTimer scheduledTimerWithTimeInterval:...]
。 GCD工作线程不运行运行循环。 这就是为什么你的第一次尝试不起作用的原因。
当您尝试[[NSRunLoop mainRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode]
,您正在从GCD工作线程向主运行循环发送消息。 NSRunLoop
存在的问题不是线程安全的。 (这在NSRunLoop类参考中有记录 。)
相反,您需要调度回主队列,以便在将addTimer:...
消息发送到主运行循环时,它在主线程上完成。
-(void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSTimer *timer = [NSTimer timerWithTimeInterval:0.10
target:self
selector:@selector(action_Timer)
userInfo:nil
repeats:YES];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
});
});
}
实际上,如果您要在主运行循环中安排计时器,则没有理由在后台队列上创建计时器。 您可以调度回主队列来创建和安排它:
-(void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"on background queue");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"on main queue");
[NSTimer scheduledTimerWithTimeInterval:0.10
target:self
selector:@selector(action_Timer)
userInfo:nil
repeats:YES];
});
});
}
请注意,我的两个解决方案都将计时器添加到主运行循环中,因此计时器的操作将在主线程上运行。 如果您希望计时器的操作在后台队列上运行,您应该从操作中调度它:
-(void)action_Timer {
// This is called on the main queue, so dispatch to a background queue.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
LOG("Timer called");
});
}
您必须将计时器添加到主运行循环以启动计时器,但首先,您应该在私有ivar或属性中保持对计时器的引用:
-(void)viewDidLoad{
// on the main queue
self.mytimer = [NSTimer scheduledTimerWithTimeInterval:0.10
target:self
selector:@selector(action_Timer)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode];
}
-(void)action_Timer{
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
LOG("Timer called");
});
}
我发现在被调用的方法中更容易脱离主队列。 在某些点,也许在viewDidUnlod
或dealloc
,你将调用[self.myTimer invalidate]; self.myTimer = nil;
[self.myTimer invalidate]; self.myTimer = nil;
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.