Skip to content

Instantly share code, notes, and snippets.

@stevenojo
Last active May 6, 2023 23:56
Show Gist options
  • Save stevenojo/e1dcc2b3e2fd4ed1f411eef88e254cb0 to your computer and use it in GitHub Desktop.
Save stevenojo/e1dcc2b3e2fd4ed1f411eef88e254cb0 to your computer and use it in GitHub Desktop.
Objective-C Debounce Example Using GCD Dispatch Sources / Timer

##Debouncing using GCD on iOS

The idea of "Debouncing" is to limit the rate a function or task can execute by waiting a certain amount of time before executing it. In the example below, if a user rapidly enters input, it will only execute once, 1 second after all that input. This is the implementation of a sample class showing how to do so, while using Grand Central Dispatch to create a timer. The timer fires on a global queue in this example - but you can change the queue to any queue where you want the timer to execute, regardless of where you set it up.

#import <Foundation/Foundation.h>

@interface DebounceExample : NSObject
@property(strong) dispatch_source_t debounceTimer;
@end

@implementation DebounceExample

dispatch_source_t CreateDebounceDispatchTimer(double debounceTime, dispatch_queue_t queue, dispatch_block_t block) {
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    if (timer) {
        dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, debounceTime * NSEC_PER_SEC), DISPATCH_TIME_FOREVER, (1ull * NSEC_PER_SEC) / 10);
        dispatch_source_set_event_handler(timer, block);
        dispatch_resume(timer);
    }
    
    return timer;
}

- (void)doSomethingRepeatedlyThatShouldBeLimitedWithText:(NSString*)text {
    if (self.debounceTimer != nil) {
        dispatch_source_cancel(self.debounceTimer);
        self.debounceTimer = nil;
    }
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    double secondsToThrottle = 1.000f;
    self.debounceTimer = CreateDebounceDispatchTimer(secondsToThrottle, queue, ^{
        //Do some task you don't want to happen every character change, like filter a large set of data or query the network, update a scrubber position.
        //[self doSomethingWith:text];
    });
}

- (IBAction) filterTextChanged:(UITextField*)someTextField {
    [self doSomethingRepeatedlyThatShouldBeLimitedWithText:someTextField.text];
}
@end
@jenel-adrise
Copy link

great job!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment