Tickers in Objective-C

Timers are for when you want to do something once in the future - tickers are for when you want to do something repeatedly at regular intervals. Here’s an example of a ticker that ticks periodically until we stop it.

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // Tickers use a similar mechanism to timers: a dispatch source that fires at regular intervals.
        // Here we'll use a dispatch source to create events every 500ms.
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
        dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), 500 * NSEC_PER_MSEC, 100 * NSEC_PER_MSEC);
        
        __block BOOL shouldStop = NO;
        
        dispatch_source_set_event_handler(timer, ^{
            if (shouldStop) {
                dispatch_source_cancel(timer);
                return;
            }
            
            NSDate *currentTime = [NSDate date];
            NSLog(@"Tick at %@", currentTime);
        });
        
        dispatch_resume(timer);
        
        // We'll stop our ticker after 1600ms.
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1600 * NSEC_PER_MSEC), dispatch_get_main_queue(), ^{
            shouldStop = YES;
            NSLog(@"Ticker stopped");
        });
        
        // Keep the main thread alive
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

When we run this program the ticker should tick 3 times before we stop it.

$ gcc -framework Foundation ticker.m -o ticker
$ ./ticker
2023-06-08 15:30:00.123 ticker[12345:67890] Tick at 2023-06-08 15:30:00 +0000
2023-06-08 15:30:00.623 ticker[12345:67890] Tick at 2023-06-08 15:30:00 +0000
2023-06-08 15:30:01.123 ticker[12345:67890] Tick at 2023-06-08 15:30:01 +0000
2023-06-08 15:30:01.623 ticker[12345:67890] Ticker stopped

In this Objective-C version, we use Grand Central Dispatch (GCD) to create a timer that fires every 500 milliseconds. The dispatch_source_t is similar to a ticker in that it repeatedly performs an action at regular intervals. We use a block to handle each tick event, printing the current time.

Instead of using channels like in the original example, we use a boolean flag shouldStop to control when the ticker should stop. After 1600 milliseconds, we set this flag to YES, which causes the ticker to stop on its next iteration.

Note that Objective-C and the iOS/macOS frameworks don’t have a direct equivalent to Go’s ticker, but the combination of GCD’s timer source and dispatch queues provides similar functionality.