Simple throttling of blocks using dispatch sources.
#import <Foundation/Foundation.h> | |
@interface JNWThrottledBlock : NSObject | |
// Runs the block after the buffer time _only_ if another call with the same identifier is not received | |
// within the buffer time. If a new call is received within that time period the buffer will be reset. | |
// The block will be run on the main queue. | |
// | |
// Identifier and block must not be nil. | |
+ (void)runBlock:(void (^)())block withIdentifier:(NSString *)identifier throttle:(CFTimeInterval)bufferTime; | |
@end |
#import "JNWThrottledBlock.h" | |
@implementation JNWThrottledBlock | |
+ (NSMutableDictionary *)mappingsDictionary { | |
static NSMutableDictionary *mappings = nil; | |
static dispatch_once_t onceToken; | |
dispatch_once(&onceToken, ^{ | |
mappings = [NSMutableDictionary dictionary]; | |
}); | |
return mappings; | |
} | |
+ (void)runBlock:(void (^)())block withIdentifier:(NSString *)identifier throttle:(CFTimeInterval)bufferTime { | |
if (block == NULL || identifier == nil) { | |
NSAssert(NO, @"block or identifier must not be nil"); | |
} | |
dispatch_source_t source = self.mappingsDictionary[identifier]; | |
if (source != nil) { | |
dispatch_source_cancel(source); | |
} | |
source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); | |
dispatch_source_set_timer(source, dispatch_time(DISPATCH_TIME_NOW, bufferTime * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, 0); | |
dispatch_source_set_event_handler(source, ^{ | |
block(); | |
dispatch_source_cancel(source); | |
[self.mappingsDictionary removeObjectForKey:identifier]; | |
}); | |
dispatch_resume(source); | |
self.mappingsDictionary[identifier] = source; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment