全局队列中的定时器不在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类参考中有logging

相反,您需要重新发送到主队列,以便在将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]; }); }); } 

实际上,如果要在主运行循环中安排计时器,则没有必要在后台队列上创build计时器。 您只需发送回主队列即可创build并安排它:

 -(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]; }); }); } 

请注意,我的两个解决scheme都将计时器添加到主运行循环中,所以计时器的动作将在主线程上运行。 如果你想让定时器的动作在后台队列上运行,你应该从动作中调度它:

 -(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"); }); } 

我发现在被调用的方法中更容易下主队列。 在某些时候,也许在viewDidUnloddealloc ,你将有调用[self.myTimer invalidate]; self.myTimer = nil; [self.myTimer invalidate]; self.myTimer = nil;

  • 的NSTimer
  • NSRunLoop
  • NSObject的