我正在尝试创建一个这样的循环:
while (TRUE){
dispatch_after(...{
<some action>
});
}
在viewDidLoad之后。我的想法是重复重复dispatch_after。 dispatch_after在执行操作之前等待两秒钟。
这不起作用 - 屏幕只是空白?它是否陷入循环或......?
答案 0 :(得分:12)
是的,你可以用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);
}
测试!按预期工作。
答案 1 :(得分:6)
无论计划何时运行,dispatch_after(...)
调用都会立即返回。这意味着你的循环在调度它们之间不会等待两秒钟。相反,你正构建一个从现在起两秒钟内发生的无限队列,而不是彼此之间的两秒钟。
所以是的,你陷入无限循环中,需要添加越来越多的块来执行。如果你想要每两秒钟发生一次事情,那么你可以使用一个重复的NSTimer或者在其自身内部使用块dispatch_after(这样第二个块在第一个块之后运行两秒钟)。
答案 2 :(得分:5)
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);
}
答案 3 :(得分:1)
如果您希望在延迟检查之后运行异步任务,例如标签是否已更新,则完成后,您可以使用以下代码:
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);
}];
}];