Run repeating NSTimer with GCD?

grand-central-dispatch, ios, nsrunloop, nstimer, objective-c

Solution

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:

- 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.

- 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.

- 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?

Problem

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

Original source