0

我有一个dispatch_source_t我正在尝试使用的问题。我想用它来延迟 a 的处理PHChange5 秒,因为 aPHChange可以在短时间内发生多次。我将不胜感激提供的任何帮助。本质上,我想取消之前的dispatch_source_t计时器,就像NSTimer.

@property (nonatomic, strong) dispatch_source_t libraryChangedTimer;

dispatch_source_t CreateTimerDispatchSource(uint64_t interval, uint64_t leeway, 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_walltime(NULL, 0), interval, leeway);

        dispatch_source_set_event_handler(timer, block);

        dispatch_resume(timer);
    }

    return timer;
}

- (void)libraryChanged:(PHChange *)changeInstance
{
    NSLog(@"Called immediately and it shouldn't");
}

- (void)photoLibraryDidChange:(PHChange *)changeInstance
{
    if (self.libraryChangedTimer)
    {
        dispatch_source_cancel(self.libraryChangedTimer);

        self.libraryChangedTimer = CreateTimerDispatchSource(5ull * NSEC_PER_SEC, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^
        {
            [self libraryChanged:changeInstance];
            dispatch_source_cancel(self.libraryChangedTimer);
        });
    }
    else
    {
        self.libraryChangedTimer = CreateTimerDispatchSource(5ull * NSEC_PER_SEC, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^
        {
            [self libraryChanged:changeInstance];
            dispatch_source_cancel(self.libraryChangedTimer);
        });
    }
}
4

2 回答 2

2

你的问题是这一行:

    dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);

实际上,您指定“现在”作为计时器的开始时间。就是这样dispatch_walltime(NULL, 0)计算的。您将您的interval值作为计时器的间隔传递,这要求它在两次触发之间重复该时间段。但是开始时间决定了第一次射击的时间。

你想要的是:

    dispatch_source_set_timer(timer, dispatch_walltime(NULL, interval), interval, leeway);

或者,如果您实际上不希望计时器重复:

    dispatch_source_set_timer(timer, dispatch_walltime(NULL, interval), DISPATCH_TIME_FOREVER, leeway);
于 2015-06-07T23:25:42.440 回答
1

我通过使用dispatch_after代码很简单地解决了这个问题:

dispatch_source_t CreateTimerDispatchSource(uint64_t interval, uint64_t leeway, 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_walltime(NULL, 0), DISPATCH_TIME_FOREVER, leeway);

        dispatch_source_set_event_handler(timer, block);

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, interval), queue,^
        {
            dispatch_resume(timer);
        });
    }

    return timer;
}

- (void)libraryChanged:(PHChange *)changeInstance
{
    // Do something 
}

- (void)photoLibraryDidChange:(PHChange *)changeInstance
{
    if (self.libraryChangedTimer)
    {
        dispatch_source_cancel(self.libraryChangedTimer);

        self.libraryChangedTimer = CreateTimerDispatchSource(5ull * NSEC_PER_SEC, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^
        {
            [self libraryChanged:changeInstance];
            dispatch_source_cancel(self.libraryChangedTimer);
            self.libraryChangedTimer = nil;
        });
    }
    else
    {
        self.libraryChangedTimer = CreateTimerDispatchSource(5ull * NSEC_PER_SEC, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^
        {
            [self libraryChanged:changeInstance];
            dispatch_source_cancel(self.libraryChangedTimer);
            self.libraryChangedTimer = nil;
        });
    }
}
于 2015-06-07T22:40:54.557 回答