Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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
You can’t perform that action at this time.