Блоки для контура обратных вызовов с пользовательского интерфейса


У меня есть трудоемкий процесс и индикатор прогресса, показывающий пользователю, как далеко все зашло. Поскольку я должен сделать потребляющую вещь в главном потоке, у меня нет возможности просто отправлять обновление в основную очередь между обновлениями. Я должен переключиться на фоновый поток на мгновение, чтобы позволить 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);
1 2

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];
    }
}
Вам вообще не нужен фоновый поток (особенно когда все, что он делает, это спит).