У меня есть стек Core Data с основным контекстом управляемых объектов с NSMainQueueConcurrencyType.Private NSManagedObjectContexts и удаление объектов
Пользователь может инициировать задачу на управляемый объект, который может занять много времени, поэтому она выполняется на отдельном контексте:
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[context setParentContext:mainMOC];
Person *samePerson = (Person *)[context objectWithID:person.objectID];
[context performBlock:^{
// BLOCK 1
// do lots of work
// then update the managed object
samePerson.value = someCalculatedValue;
// save the private context
NSError *error;
if (![context save:&error]) {
NSLog(@"Error: %@", error);
}
[mainMOC performBlock:^{
NSError *error;
if (![mainMOC save:&error]) {
NSLog(@"Error saving: %@", error);
}
}];
}];
Это прекрасно работает, и главный MOC обновляется должным образом, NSFetchedResultsController подключен к нему надлежащим образом и т. д.
Проблема с удалением. Я имею эту установку для удаления объектов:
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[context setParentContext:mainMOC];
[context performBlock:^{
// BLOCK 2
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Person"];
NSError *error;
NSArray *all = [context executeFetchRequest:request error:&error];
if (!all) {
NSLog(@"Error fetching: %@", error);
} else {
for (NSManagedObject *person in all) {
[context deleteObject:person];
}
NSError *error;
if (![context save:&error]) {
NSLog(@"Error saving: %@", error);
}
[mainMOC performBlock:^{
NSError *error;
if (![mainMOC save:&error]) {
NSLog(@"Error saving: %@", error);
}
}];
}
}];
Теперь, если я эта операции удаления (блок 2) в течение времени, необходимым для выполнения длительной задачи (блок 1), то УДАЛИТЬ операция быстро заканчивается и сохраняется в основном контексте. Через некоторое время блок 1 заканчивается, и когда она сохраняет mainMOC в его конце, мы получаем, казалось бы, очевидный крах:
CoreData could not fulfill a fault for ...
Мой вопрос: как я могу выполнить задачи, такие как блок 1 с возможностью его объект удаляется?
Я думаю, мне было интересно, был ли лучший образец для работы с удаленными управляемыми объектами в многопоточной среде. Я надеялся на что-то другое, кроме синхронизации или использования последовательной очереди. В противном случае весь мой управляемый объектный код потребует таких семафоров, не так ли? – raheel
Посмотрите на установку mergePolicy в своем контексте и попробуйте ответить на сохранение как с помощью mergeChangesFromContextDidSaveNotification: чтобы попытаться объединить изменения из вашего удаления в работу, выполняемую в длинном контексте, перед сохранением. У вас есть два разных контекста, наступающих друг на друга, - будет какая-то работа, связанная с тем, чтобы заставить их сосуществовать - либо объединить изменения, либо разделить их. –