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 に答える