Instantly share code, notes, and snippets.

What would you like to do?
Using grand central dispatch to run a callback after a delay, with hacky partial cancellation. Cancelling allows the callback to be deallocated, but doesn't completely clean up what's in GCD.
+(void) runBlock:(VoidBlock)callback
unless:(TOCCancelToken*)unlessCancelledToken {
__block VoidBlock callbackForBlock = callback;
NSObject* lock = [NSObject new];
VoidBlock allowDeallocWrapper = ^{
VoidBlock callbackPeek;
@synchronized(lock) {
callbackPeek = callbackForBlock;
if (callbackPeek == nil) return; // cancelled
const int nanosPerSec = 1000*1000*1000;
// simplification: just assume the double to dispatch_time_t conversion is going to work
dispatch_time_t callTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds / nanosPerSec));
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
// Simplification: assuming the cancellation token is not long lived (will discuss)
[unlessCancelledToken whenCancelledDo:^{
@synchronized(lock) {
callbackForBlock = nil;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment