Reputation: 15588
I have some code that uses a fair amount of GCD code. I need to implement a way to schedule a unit of work after some delay, but can be canceled and moved further out if needed.
Think of a handler for clicks; something to distinguish single clicks from double clicks. To do this, one would get the click event, and set up a short timer to act on it. If another click event came through before the timer fired, it would be canceled and started again. When the timer did eventually fire, it would have the correct number of clicks.
Anyways, this would be easy enough to implement with NSTimers or the performSelector stuff on NSObject. Maybe something like
NSUInteger tapCount = 0;
- (void)handleClickEvent
{
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(fireEvent:) object:nil];
tapCount++;
[self performSelector:@selector(fireEvent:) withObject:@(tapCount) afterDelay:2.0];
}
- (void)fireEvent:(NSNumber *)clickCount
{
// Act on the coalesced event
NSUInteger numClicks = [clickCount unsignedIntegerValue];
if ( numClicks == 1 ) // single click
if ( numClicks == 2 ) // double click
}
Before doing it this way however, I am wondering if there is a way to do this with the GCD functions. I know you can't undo enqueueing a block, so dispatch_after isn't really an option. I know there are dispatch timer sources, but they seem like they are more used for firing periodic tasks. I don't know if they can be easily canceled and started later like I would need.
Thanks for any suggestions.
Upvotes: 2
Views: 1501
Reputation: 3681
dispatch_source_set_timer() will reschedule a dispatch timer source (which can be one-shot and non-repeating if you pass DISPATCH_TIME_FOREVER as the interval parameter).
Note that this API is non-preemptive, i.e. unless you call dispatch_source_set_timer() from the target queue of the timer source, the timer handler could already be running at the time of reschedule.
However, once dispatch_source_set_timer() returns, it is guaranteed that the timer will no longer fire at the previously set target time.
Upvotes: 8