В настоящее время я занимаюсь разработкой приложения для iPhone с использованием CoreData в качестве слоя сохранения данных.В одном из сценариев мне нужно выполнить некоторые управляемые объекты обработки и пакетного обновления в фоновом режиме, чтобы не блокировать поток пользовательского интерфейса.
Следуя Рекомендации Apple по этому вопросу, у меня есть 2 разныхконтексты управляемого объекта (один для основного потока, один для фонового потока).Вот код распределения (в моем делегате приложения):
// Object context for Main Thread
_managedObjectContext = [[NSManagedObjectContext alloc] init];
_managedObjectContext.persistentStoreCoordinator = _coordinator;
// Object context for the background thread
dispatch_group_t myGroup = dispatch_group_create();
dispatch_group_async(
myGroup,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0),
^{
_bgManagedObjectContext = [[NSManagedObjectContext alloc] init];
_bgManagedObjectContext.persistentStoreCoordinator = _coordinator;
}
);
dispatch_group_wait(myGroup, DISPATCH_TIME_FOREVER);
dispatch_release(myGroup);
Когда приложение запускается, основной поток только выбирает объект для отображения, в то время как фоновый поток получает свежие данные из сети и обновляет CoreData.
Я использую для этого AFNetworking и проверяю, чтобы все обратные вызовы выполнялись в фоновом потоке.Фрагмент:
NSURLRequest *request = [NSURLRequest requestWithURL:webserviceURL];
AFHTTPRequestOperation *operation =
[[[AFHTTPRequestOperation alloc] initWithRequest:request] autorelease];
[operation setCompletionBlockWithSuccess:
^(AFHTTPRequestOperation *operation, id responseObject) {
// Getting the managed object context created on the bg thread
NSManagedObjectContext *context = [self bgManagedObjectContext];
//
// Snip...
// Fetch objects, update them
//
} failure:nil];
operation.successCallbackQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
[operation start];
В коде обратного вызова я выбираю свежие объекты на основе их свойств, а затем обновляю их.Все хорошо и замечательно, пока я не начну обновлять связанные объекты ...
Моя основная сущность (Place
) определяет одностороннее отношение один-ко-многим к Keyword
(полнотекстовый поиск бедняка ...) и когда я переиндексирую Place
, я начинаю с удаления всех связанных Keyword
с.
// `self.searchWords` is a @dynamic property
for (NSManagedObject *word in self.searchWords) {
// context is still the background thread's object context
// and we're still on the background thread
[context deleteObject:word];
}
[self removeSearchWords:oldSearchWords];
При достижении [context deleteObject:word]
, я 'получаю исключение: NSManagedObjectContext не может удалять объекты в других контекстах
Когда я отлаживаю и проверяю переменные, я вижу, что:
self._cd_managedObjectContext
контекст объекта фонового потока word._cd_managedObjectContext
является контекстом объекта основного потока
Я нахожу это совершенно запутанным, я не понимаю, почему извлеченные отношения в конечном итоге ассоциируются сдругой контекст объекта.
Я мог бы в итоге повторно извлечь связанный Keyword
в фоновом контексте, а затем удалить его отсюда, но является ли это единственным решением в этом случае?Или я что-то не так делаю?