dispatch_after具有滑动或可重置延迟

时间:2015-03-04 20:12:32

标签: ios objective-c grand-central-dispatch

我正在显示一个UIView,用于显示用户为其他目的标记的地图功能的信息,例如删除或编辑。标记功能时,我显示的是包含信息和撤消选项的UIView。在一段固定的时间内显示UIView已经完成并正常工作,但是,我希望延迟有一个滑动到期,也就是说,如果用户选择另一个地图要素进行标记,延迟应该自行重置并且UIView应该在指定的全部时间内保持可见。我正在寻找的是滑动过期。到目前为止我的代码:

double delaySeconds = 15;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [self toggleUndoViewToShow:NO];
});

所以,我的延迟时间是15秒,如果在这15秒内标记了另一个功能,我希望视图在整个延迟时间内保持可见状态。我怎么能这样做?谢谢!

2 个答案:

答案 0 :(得分:3)

使用计时器调度源。使用dispatch_source_create()创建它,并将DISPATCH_SOURCE_TYPE_TIMER作为类型传递。致电dispatch_source_set_timer()设置开始时间。要模拟仅运行其任务一次的dispatch_after(),请使用DISPATCH_TIME_FOREVER作为间隔。调用dispatch_source_set_event_handler()将任务设置为在指定时间到达时执行。此外,任务需要使用dispatch_source_cancel()取消源以清理源。在源上调用dispatch_resume()以允许它(它在暂停状态下创建)。

您可以随时使用dispatch_source_set_timer()来调整任务运行的时间。您也可以随时取消它。

由于这比dispatch_after()稍微复杂一些,您可以将其包装在帮助器中以便为您设置。辅助函数的调用者将提交一个不知道取消源的需要的任务块。您的助手会将其包装在调用提供的块的任务中,然后执行dispatch_source_cancel()


对于您需要的非常简单的情况,上述情况可能有点过分。你也可以这样做:

__block int savedTaskID;
if ([NSThread isMainThread])
    savedTaskID = ++self.currentTaskID; // an integer property on your view
else dispatch_sync(dispatch_get_main_queue(), ^{
    savedTaskID = ++self.currentTaskID;
});

double delaySeconds = 15;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delaySeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    if (savedTaskID == self.currentTaskID)
        [self toggleUndoViewToShow:NO];
});

如果您想延迟切换,只需重复上述步骤即可。由于增加currentTaskID,当先前提交的任务运行时,它们什么都不做。这有点浪费,因为绝对的任务仍然存在并最终运行,但听起来不会发生太多。

答案 1 :(得分:1)

根据我的理解,您需要取消计划在某个延迟后执行的现有块,并以15秒的新延迟安排等效块。 This应该可以帮助您取消计划运行的延迟块。