2017-01-31 19 views
1

У меня есть процесс синхронизации iOS, разбитый на ряд асинхронных подклассов NSOperation. Они подразделяются на те, которые выполняют тяжелую обработку, и те, которые полагаются на сеть. Но большинство из них также делают вещи с Core Data.Использование данных ядра в асинхронной операции

Я не уверен, как выполнять операции с основными данными в рамках операции.

Вот несколько простых примеров ... мой настоящий код делает несколько переключателей в и из контекста базы данных. Он также использует @synchronize(self){}.

NSManagedContext *context = [self newContextFromParent]; 
__block NSString *someValue; 
[context performBlockAndWait:^{ 
    // fetch someValue from Core Data 
}]; 
[self doMoreWorkWithValue:someValue]; 
[context performBlockAndWait:^{ 
    NSError *e; 
    if ([context hasChanges]) { 
     [context saveChanges:&e]; 
    } 
}]; 

Это, кажется, на поверхности, как хороший подход, но в зависимости от того, что я делаю в performBlockAndWait: есть потенциальные тупики здесь.

Как правило, я хотел бы избежать performBlockAndWait: в своем коде и использовать вместо него performBlock:.

[context performBlock:^{ 
    NSString *someValue = @""; // fetch someValue from Core Data 
    [backgroundQueue addOperationWithBlock:^{ 
     [self doMoreWorkWithValue:someValue withCompletion:^{ 
      [context performBlock:^{ 
       NSError *e; 
       if ([context hasChanges]) { 
        [context saveChanges:&e]; 
       } 
      }]; 
     }]; 
    }]; 
}]; 

При таком подходе, хотя, я переместил свою обработку из потока, у меня был к тому, что нити backgroundQueue решает запустить свой процесс, и я не уверен, что лучший подход.

Если я захватил [NSOperation currentQueue] в основной операции и добавлю вместо этого, я добавил свой блок в конец очереди. Я действительно хочу возобновить.

Какой подход я должен использовать здесь?

ответ

1

Ваш первый подход - это тот, который я бы использовал. Тем не менее, вы упомянули о тупиках внутри performBlockAndWait:. Вас беспокоит вызов другого метода, который мог бы использовать performBlockAndWait:? Если это так, не беспокойтесь; performBlockAndWait: явно безопасно использовать повторно. То есть: этот код является безопасным (хотя, очевидно, надуманным):

[context performBlockAndWait:^{ 
    [context performBlockAndWait:^{ 
     // fetch someValue from Core Data 
    }]; 
}]; 

Если тупиковая озабоченность не связана с Core Data, то кажется, что вы хотите быть так же, как много риска тупика внутри doMoreWorkWithValue: , правильно?

+0

Да. После того, как я прочитал ваш ответ, я думаю, что реальный ответ должен быть более осторожным с моими блоками '@synchronized {}' и рассматривать их как настоящую проблему. 'performBlockAndWait:' и '@synchronized {}' оба являются разумными сами по себе, но как только они вложены, я играю с огнем. Это правильно? –

+0

Основная проблема, которую я вижу, заключается в том, что 'performBlockAndWait:' _might_ выполняется в другом потоке (или может не быть), а '@ synchronized' - механизм блокировки на основе потоков. В общем, я стараюсь избегать вызова других методов на 'self' из блока' @ synchronized'; он должен защищать очень небольшой регион. –

+0

Должно быть хорошо использовать '@synchronized {}' из 'executeBlockAndWait:'; просто не делайте этого наоборот. Не вызывайте 'performBlockAndWait:' из блока '@synchronized {}'. –

 Смежные вопросы

  • Нет связанных вопросов^_^