【问题标题】:A blocks for-loop with UI callbacks带有 UI 回调的块 for 循环
【发布时间】:2012-07-26 10:58:17
【问题描述】:

我有一个耗时的过程,并且有一个进度指示器向用户显示事情已经完成了多远。因为我必须在主线程上做消耗的事情,所以我没有选择在更新之间简单地在主队列上分派更新。我必须暂时切换到后台线程,以便在切换回并继续之前让 UI 更新。

这是我拥有的,但感觉很不正统。有没有更好的方法来执行我缺少的“带有回调到 UI 的循环块”?我也不完全确定这是否真的会最终释放块,但这是另一回事。

__block NSUInteger i = 0;
__block dispatch_block_t obtainBlock;

obtainBlock = [^{
    [self obtainAssetAtIndex:i];
    progressView.progress += progressPerFile;
    i++;
    if (i < assets.count) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
            usleep(500);
            dispatch_async(dispatch_get_main_queue(), obtainBlock);
        });
    } else {
        [self didImportGroup];
        [obtainBlock release];
    }
} copy];

dispatch_async(dispatch_get_main_queue(), obtainBlock);

【问题讨论】:

  • 您需要在else 子句中设置obtainBlock = nil 以解除分配块。为什么要在主线程上消费?
  • 为什么我需要将它设置为 nil?它在对块的最终调用中被释放。
  • 你是对的。我错过了。

标签: ios optimization for-loop objective-c-blocks grand-central-dispatch


【解决方案1】:

思路太复杂了。当前设置:

  1. 做一件工作
  2. 将控制权交给后台线程
  3. 在后台睡觉
  4. 在主线程上安排下一项工作

你想做什么:

  1. 做一件工作
  2. 安排下一项工作

代码如下:

- (void)doWork
{
    if (_assetIndex < assets.count) {
        [self obtainAssetAtIndex:_assetIndex++];
        progressView.progress += progressPerFile;
        [self performSelector:@selector(doWork) withObject:nil afterDelay:0];
    } else {
        [self didImportGroup];
    }
}

您根本不需要后台线程(尤其是当它所做的只是休眠时)。

【讨论】:

  • 呻吟 谢谢。我不知道我在想什么。显然你就是这样做的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-06
  • 2013-10-08
  • 2015-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多