У меня есть процесс синхронизации 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]
в основной операции и добавлю вместо этого, я добавил свой блок в конец очереди. Я действительно хочу возобновить.
Какой подход я должен использовать здесь?
Да. После того, как я прочитал ваш ответ, я думаю, что реальный ответ должен быть более осторожным с моими блоками '@synchronized {}' и рассматривать их как настоящую проблему. 'performBlockAndWait:' и '@synchronized {}' оба являются разумными сами по себе, но как только они вложены, я играю с огнем. Это правильно? –
Основная проблема, которую я вижу, заключается в том, что 'performBlockAndWait:' _might_ выполняется в другом потоке (или может не быть), а '@ synchronized' - механизм блокировки на основе потоков. В общем, я стараюсь избегать вызова других методов на 'self' из блока' @ synchronized'; он должен защищать очень небольшой регион. –
Должно быть хорошо использовать '@synchronized {}' из 'executeBlockAndWait:'; просто не делайте этого наоборот. Не вызывайте 'performBlockAndWait:' из блока '@synchronized {}'. –