Created
April 18, 2016 14:30
-
-
Save jeffaburt/2144270416bd148901271ef7f60656a4 to your computer and use it in GitHub Desktop.
dispatch_after with the ability to cancel execution
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// DispatchAfterWithCancel.h | |
// | |
// Created by Jeff Burt on 4/18/16. | |
// Copyright © 2016 Jeff Burt. All rights reserved. | |
// | |
#ifndef DispatchAfterWithCancel_h | |
#define DispatchAfterWithCancel_h | |
typedef void(^dispatch_after_with_cancel_t)(BOOL shouldCancel); | |
/** | |
* Provides a dispatch_after block that can be canceled before its execution. | |
* The block will be called on the main thread. | |
* | |
* To cancel the block before it executes, simply call `cancel_block` with | |
* the block returned by this function. | |
* | |
* This function will always return a non-null `dispatch_after_with_cancel_t` | |
* block, even if the `block` provided is NULL. | |
* | |
* @param delay the time to wait before execution | |
* @param block the block to execute | |
* | |
* @return a block that will execute after the set delay. Calling `cancel_block` | |
* with this block will cancel the block before it executes. | |
*/ | |
NS_INLINE dispatch_after_with_cancel_t dispatch_after_with_cancel(NSTimeInterval delay, dispatch_block_t block) { | |
__block dispatch_block_t originalBlock = [block copy]; | |
__block dispatch_after_with_cancel_t cancelableBlock = ^(BOOL shouldCancel) { | |
if (shouldCancel == NO && originalBlock) { | |
originalBlock(); | |
} | |
originalBlock = NULL; | |
}; | |
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ | |
if (cancelableBlock) { | |
cancelableBlock(NO); | |
cancelableBlock = NULL; | |
} | |
}); | |
return cancelableBlock; | |
} | |
/** | |
* Cancels the block before it executes. Does nothing when a NULL block is | |
* provided. | |
* | |
* @param block the block to cancel | |
*/ | |
NS_INLINE void cancel_block(dispatch_after_with_cancel_t block) { | |
if (block) { | |
block(YES); | |
block = NULL; | |
} | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ViewController.m | |
// | |
// Created by Jeffrey Burt on 4/18/16. | |
// Copyright © 2016 Jeff Burt. All rights reserved. | |
// | |
#import "ViewController.h" | |
#import "DispatchAfterWithCancel.h" | |
@implementation ViewController | |
- (void)viewDidLoad { | |
[super viewDidLoad]; | |
dispatch_after_with_cancel_t block = dispatch_after_with_cancel(3, ^{ | |
NSLog(@"Hello world!"); | |
}); | |
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ | |
NSLog(@"Canceling block early"); | |
cancel_block(block); | |
}); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Looks like somebody is psyching up for an upcoming Facebook interview and a potential move to the Left Coast. The original Glassdoor article (and question) you're responding to is mine. 😜 Best of luck to you.