dispatch_after循环/重复

我想创建一个这样的循环:

while (TRUE){ dispatch_after(...{  }); } 

在viewDidLoad之后。 我的想法是重复重复dispatch_after。 dispatch_after在执行操作之前等待两秒钟。

这不起作用 – 屏幕只是空白? 它是否陷入循环或……?

无论何时调度运行, dispatch_after(...)调用都会立即返回。 这意味着您的循环在分派它们之间不会等待两秒钟。 相反,你正构建一个无限的队列,从现在开始两秒钟,而不是两秒钟之间。

所以是的,你陷入无限循环中,需要添加越来越多的块来执行。 如果你想要每两秒钟发生一次事情,那么你可以使用重复的NSTimer或者在其内部使用块dispatch_after(这样第二个块在第一个块之后运行两秒钟)。

是的,你可以用gcd做到这一点。 但是你需要两个额外的c函数。

 static void dispatch_async_repeated_internal(dispatch_time_t firstPopTime, double intervalInSeconds, dispatch_queue_t queue, void(^work)(BOOL *stop)) { __block BOOL shouldStop = NO; dispatch_time_t nextPopTime = dispatch_time(firstPopTime, (int64_t)(intervalInSeconds * NSEC_PER_SEC)); dispatch_after(nextPopTime, queue, ^{ work(&shouldStop); if(!shouldStop) { dispatch_async_repeated_internal(nextPopTime, intervalInSeconds, queue, work); } }); } void dispatch_async_repeated(double intervalInSeconds, dispatch_queue_t queue, void(^work)(BOOL *stop)) { dispatch_time_t firstPopTime = dispatch_time(DISPATCH_TIME_NOW, intervalInSeconds * NSEC_PER_SEC); dispatch_async_repeated_internal(firstPopTime, intervalInSeconds, queue, work); } 

经测试! 按预期工作。

https://gist.github.com/4676773

GCD已经内置了这个

 dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); if (timer) { dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), interval * NSEC_PER_SEC, (1ull * NSEC_PER_SEC) / 10); dispatch_source_set_event_handler(timer, block); dispatch_resume(timer); } 

https://gist.github.com/maicki/7622108

如果您希望在延迟检查之后运行异步任务,例如,如果标签已更新,则完成后,您可以使用以下代码:

 typedef void (^RepeatCompletionHandler)(BOOL isRepeat); typedef void (^RepeatBlock)(RepeatCompletionHandler completionHandler); - (void)dispatchRepeat:(int)seconds withBlock:(RepeatBlock)block { dispatch_after(dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC), dispatch_get_main_queue(), ^() { block(^(BOOL isRepeat) { if (isRepeat) { return [self dispatchRepeat:seconds withBlock:block]; } }); }); } 

例如:

 [self dispatchRepeat:5 withBlock:^(RepeatCompletionHandler completionHandler) { [tagsService getTagValueForTagName:TagName value:^(NSString *tagValue) { if (![TagValue isEqualToString:tagValue]) { return completionHandler(YES); } completionHandler(NO); }]; }];