4

我正在尝试创建一个这样的循环:

while (TRUE){
  dispatch_after(...{
    <some action>
  });
}

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

这不起作用 - 屏幕只是空白?它卡在循环中还是...?

4

4 回答 4

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);
}

经测试!按预期工作。

https://gist.github.com/4676773

于 2013-01-29T12:32:07.637 回答
6

dispatch_after(...)无论计划何时运行,调用都会立即返回。这意味着您的循环在调度它们之间不会等待两秒钟。相反,您正在构建一个无限的队列,这些队列将在两秒后发生,而不是彼此之间的两秒。

所以是的,您陷入了添加越来越多要执行的块的无限循环中。如果您希望每两秒发生一次,那么您可以使用重复的 NSTimer 或将块 dispatch_after 放在自身内部(以便第二个块在第一个块之后两秒运行)。

于 2012-07-13T06:18:14.947 回答
6

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

于 2015-12-10T08:46:18.677 回答
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);
    }];

}];
于 2016-02-19T01:35:04.353 回答