Shredder2794 Shredder2794 -4 years ago 106
iOS Question

Run repeating NSTimer with GCD?

I was wondering why when you create a repeating timer in a GCD block it doesen't work?

This works fine:

-(void)viewDidLoad{
[super viewDidLoad];
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(runTimer) userInfo:nil repeats:YES];
}
-(void)runTimer{
NSLog(@"hi");
}


But this doesent work:

dispatch_queue_t myQueue;

-(void)viewDidLoad{
[super viewDidLoad];

myQueue = dispatch_queue_create("someDescription", NULL);
dispatch_async(myQueue, ^{
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(runTimer) userInfo:nil repeats:YES];
});
}
-(void)runTimer{
NSLog(@"hi");
}

Answer Source

NSTimers are scheduled on the current thread's run loop. However, GCD dispatch threads don't have run loops, so scheduling timers in a GCD block isn't going to do anything.

There's three reasonable alternatives:

  1. Figure out what run loop you want to schedule the timer on, and explicitly do so. Use +[NSTimer timerWithTimeInterval:target:selector:userInfo:repeats:] to create the timer and then -[NSRunLoop addTimer:forMode:] to actually schedule it on the run loop you want to use. This requires having a handle on the run loop in question, but you may just use +[NSRunLoop mainRunLoop] if you want to do it on the main thread.
  2. Switch over to using a timer-based dispatch source. This implements a timer in a GCD-aware mechanism, that will run a block at the interval you want on the queue of your choice.
  3. Explicitly dispatch_async() back to the main queue before creating the timer. This is equivalent to option #1 using the main run loop (since it will also create the timer on the main thread).

Of course, the real question here is, why are you creating a timer from a GCD queue to begin with?

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download