+ (id)performBlock:(void (^)())aBlock onQueue:(dispatch_queue_t)queue afterDelay:(NSTimeInterval)delay { NSParameterAssert(aBlock != nil); __block BOOL cancelled = NO; void (^wrapper)(BOOL) = ^(BOOL cancel){ if (cancel) { cancelled = YES; return; } if (!cancelled) { aBlock(); } }; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), queue, ^{ wrapper(NO); }); return [wrapper copy]; } + (void)cancelBlock:(id)aBlock { NSParameterAssert(aBlock != nil); void (^wrapper)(BOOL) = aBlock; wrapper(YES); }