2

我有一些使用大量 GCD 代码的代码。我需要实施一种方法来安排一些延迟后的工作单元,但如果需要,可以取消并移出更远的地方。

想一想点击处理程序;区分单击和双击的东西。要做到这一点,人们会得到点击事件,并设置一个短的计时器来处理它。如果在计时器触发之前发生了另一个点击事件,它将被取消并重新开始。当计时器最终触发时,它会有正确的点击次数。

无论如何,这很容易用 NSTimers 或 NSObject 上的 performSelector 来实现。也许像

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
}

然而,在这样做之前,我想知道是否有办法使用 GCD 函数来做到这一点。我知道您无法撤消对块的排队,因此 dispatch_after 并不是一个真正的选择。我知道有调度计时器源,但它们似乎更用于触发定期任务。我不知道它们是否可以像我需要的那样轻松取消并稍后开始。

感谢您的任何建议。

4

1 回答 1

7

dispatch_source_set_timer() 将重新调度调度计时器源(如果您将 DISPATCH_TIME_FOREVER 作为间隔参数传递,它可以是一次性且非重复的)。

请注意,此 API 是非抢占式的,即除非您从计时器源的目标队列调用 dispatch_source_set_timer(),否则计时器处理程序可能在重新调度时已经在运行。

但是,一旦 dispatch_source_set_timer() 返回,就可以保证计时器将不再在之前设置的目标时间触发。

于 2013-01-11T22:47:21.470 回答