我想要一个带有 dispatch_after 语句的 for 循环。问题是 dispatch_after 调用似乎与 for 循环不一致。换句话说,我希望它只在 dispatch_after 块中的语句执行后才开始 for 循环的下一次迭代。

我该怎么做?

用例

我想在屏幕上呈现文字。传统上,我每秒显示一个单词。但是根据字长,我现在想显示更长的单词,稍长一些,较短的单词显示稍短的时间。我想呈现一个词,稍等片刻(取决于这个词的长度)然后呈现下一个词,稍等片刻,然后是下一个,依此类推。

最佳答案

这是实现这一目标的一种方法。自然,您需要用代码替换我的 NSLog 以显示单词,并用您用来确定延迟的任何函数替换我的简单 0.05 * word.length 函数,但这应该可以解决问题,并且不会阻塞呈现线程。

- (void)presentWord: (NSString*)word
{
    // Create a private, serial queue. This will preserve the ordering of the words
    static dispatch_queue_t wordQueue = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        wordQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
    });

    dispatch_async(wordQueue, ^{
        // Suspend the queue
        dispatch_suspend(wordQueue);

        // Show the word...
        NSLog(@"Now showing word: %@", word);

        // Calculate the delay until the next word should be shown...
        const NSTimeInterval timeToShow = 0.05 * word.length; // Or whatever your delay function is...

        // Have dispatch_after call us after that amount of time to resume the wordQueue.
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeToShow * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            dispatch_resume(wordQueue);
        });
    });
}

// There's nothing special here. Just split up a longer string into words, and pass them
// to presentWord: one at a time.
- (void)presentSentence: (NSString*)string
{
    NSArray* components = [string componentsSeparatedByCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
    [components enumerateObjectsUsingBlock:^(NSString* obj, NSUInteger idx, BOOL *stop) {
        [self presentWord: obj];
    }];
}

编辑:它的工作方式是我使用串行队列来维护单词的顺序。当您向 -presentWords 提交一个单词时,它会将一个块排在 wordQueue 的“后面”。当该块开始执行时,您知道 wordQueue 没有挂起(因为您在一个正在 wordQueue 上执行的块中),我们做的第一件事就是挂起 wordQueue 。由于这个块已经“在飞行中”,它将运行到完成,但在有人恢复它之前,不会从 wordQueue 运行其他块。暂停队列后,我们显示单词。它将保持显示,直到显示其他内容。然后,我们根据刚开始显示的单词的长度计算延迟,并设置一个 dispatch_after 以在该时间过去后恢复 wordQueue。当串行队列恢复时,下一个字的块开始执行,挂起队列,整个过程重复。

关于ios - 如何重复循环 dispatch_after 语句?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19096557/

10-10 09:37