如何使用GCD说明后台任务?

时间:2014-01-15 19:33:07

标签: ios objective-c grand-central-dispatch mbprogresshud

我想说明MBProgressHUD项目的进展,但是当我试用这个方法时:

- (IBAction)signInBttn:(id)sender {

    MBProgressHUD *hudd = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hudd.mode = MBProgressHUDModeAnnularDeterminate;
    hudd.labelText = @"Loading";

    __block float value = 0;
    for (int j = 0; j<2000; j++) {
        dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

            for (int i = 0; i<20000 ; i++) {

            }
            value += 0.001;
            dispatch_async( dispatch_get_main_queue(), ^{
                hudd.progress = value;
            });

        });
    }        
}

hud完全显示为100%。这仅仅是为了我的信息,我不知道如何创建计算某事的后台任务以及何时完成40%的HUD令人耳目一新,达到了40%的进步。我希望自己清楚明白,如果有人有时间帮助改进我的代码,那么非常感谢任何答案

2 个答案:

答案 0 :(得分:3)

在这种情况下,您可以通过将计数器的更新与UI中的HUD更新分离来解决问题。 Apple将此称为“WWDC 2012视频Asynchronous Design Patterns with Blocks, GCD, and XPC中的”异步更新状态“。

通常这不是必需的(大部分时间我们异步进行的操作都很慢,以至于我们没有问题),但是如果运行速度比UI快,那么可能希望跟上,你为此创建一个“调度源”。我将用UIProgressView来说明它,但同样适用于任何UI:

// create source for which we'll be incrementing a counter,
// and tell it to run the event handler in the main loop
// (because we're going to be updating the UI)

dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());

// specify what you want the even handler to do (i.e. update the HUD or progress bar)

dispatch_source_set_event_handler(source, ^{
    self.iterations += dispatch_source_get_data(source);
    [self.progressView setProgress: (float) self.iterations / kMaxIterations];
});

// start the dispatch source

dispatch_resume(source);

// now, initiate the process that will update the source

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    for (long i = 0; i < kMaxIterations; i++)
    {
        // presumably, do something meaningful here

        // now increment counter (and the event handler will take care of the UI)

        dispatch_source_merge_data(source, 1);
    }

    // when all done, cancel the dispatch source

    dispatch_source_cancel(source);
});

在我的示例中,iterations只是long属性:

@property (nonatomic) long iterations;

我将kMaxIterations常量定义如下:

static long const kMaxIterations = 10000000l;

答案 1 :(得分:0)

首先,如果你想延迟执行,请使用dispatch_after:Apple Doc,因为可能是Clang正在优化你的循环(即使它不存在)。

在该块内调用主线程上的dispatch_sync来更新UI,因为dispatch_async不能保证“均匀”执行。这样的事情应该有用......

for (...) {
    dispatch_after(<some formula of i>, DEFAULT_PRIORITY, ^{
         dispatch_sync(MAIN_QUEUE, ^{ hudd.progress = value });
    }
}