dispatch_after 具有滑动或可重置延迟
dispatch_after with a sliding or resettable delay
我正在显示一个 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 秒内标记了另一个功能,我希望视图在整个延迟时间内保持可见。我该怎么办?谢谢!
据我了解,您需要取消计划在一定延迟后执行的现有块,并安排具有 15 秒新延迟的等效块。 This 应该可以帮助您取消计划于 运行.
的延迟区块
使用计时器调度源。使用 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
,当先前提交的任务 运行 时,它们什么都不做。这有点浪费,因为已绝育的任务仍然存在并最终 运行,但听起来它不会发生太多。
我正在显示一个 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 秒内标记了另一个功能,我希望视图在整个延迟时间内保持可见。我该怎么办?谢谢!
据我了解,您需要取消计划在一定延迟后执行的现有块,并安排具有 15 秒新延迟的等效块。 This 应该可以帮助您取消计划于 运行.
的延迟区块使用计时器调度源。使用 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
,当先前提交的任务 运行 时,它们什么都不做。这有点浪费,因为已绝育的任务仍然存在并最终 运行,但听起来它不会发生太多。