Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GCD timer never fires

I have a bare single-view iOS app with the following in the -viewDidLoad of the view:

dispatch_queue_t q_default;
q_default = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, q_default); //run event handler on the default global queue
dispatch_time_t now = dispatch_walltime(DISPATCH_TIME_NOW, 0);
dispatch_source_set_timer(timer, now, 30ull*NSEC_PER_SEC, 5000ull);
dispatch_source_set_event_handler(timer, ^{
    printf("test\n");
});
dispatch_resume(timer);

This is taken directly from the docs (except for a simplified printf() argument). The block is never executed--can someone tell me why??

Additional Information

I was trying this in a larger app to no avail. I then backed out to the barebones app, tried with ARC both on and off, tried this code in -appDidFinishLaunching..., all with no luck. I can surround this code with NSLogs, both of which are printed. I've checked timer--it is not nil.

like image 917
GarlicFries Avatar asked Nov 17 '12 05:11

GarlicFries


2 Answers

So, the problem was that I'd lost my reference to timer when the surrounding scope was destroyed. Changing timer to an ivar instead of an automatic variable fixed things...

like image 132
GarlicFries Avatar answered Nov 08 '22 07:11

GarlicFries


Per the documentation of dispatch_source_create:

Dispatch sources are created in a suspended state. After creating the source and setting any desired attributes (for example, the handler or the context), your application must call dispatch_resume to begin event delivery.

So your timer never fires because it's suspended. To end its suspension you need to call dispatch_resume.

like image 40
Tommy Avatar answered Nov 08 '22 08:11

Tommy