Основные данные слияния двух управляемых объектов контекста
Мой Cocoa / Application имеет контекст управляемого объекта в главном потоке. Когда мне нужно обновить мои данные, моя программа будет:
- запуск нового потока
- Получение новых данных с сервера
- Создайте новый контекст управляемого объекта
- отправить уведомление в основной поток, чтобы объединить два контекста
Это функция, которая получает уведомление по основному потоку
- (void)loadManagedObjectFromNotification:(NSNotification *)saveNotification
{
if ([NSThread isMainThread]) {
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:saveNotification];
} else {
[self performSelectorOnMainThread:@selector(loadManagedObjectFromNotification:) withObject:saveNotification waitUntilDone:YES];
}
}
Я не получаю никаких ошибок. Моя проблема-результат слияния, он фактически объединяет управляемые объекты из обоих контекстов.
Моя сущность-это действительно простой список атрибутов и отношений.
Возможно, слиянию нужны некоторые инструкции, чтобы понять, когда обновленный управляемый объект является не новым, а отредактированной версией первого. Я предполагаю, что где-то мне нужно указать способ однозначной идентификации сущности (атрибут, например, может действовать как идентификатор) и что-то вроде политики слияния (если 2 управляемых объекта представляют тот же объект, возьмите тот, у которого последняя дата модификации более поздняя).
Мне просто нужно понять, как правильно объединить 2 контекста, чтобы иметь одну обновленную копию для каждого объекта.Обновление 1
Теперь эта проблема мне ясна. Контекст 2 имеет большое различие: ObjectID. В то время как контекст в главном потоке извлекает объекты ManagedObjects с помощью координатора постоянного хранилища, второй поток создает эти объекты, извлекая удаленный URL-адрес. Даже если ... объекты имеют одинаковое содержание, они будут иметь 2 различных objectID.Мои объекты уже имели уникальный идентификатор, я мог использовать setObjectId для установки этого значения. (Документация Apple говорит, что это не очень хорошая идея).
1 ответ:
Вот что вам нужно сделать, чтобы правильно объединить контексты. Во-первых, вам не нужно ваше собственное уведомление. Выполнение операции сохранения контекста автоматически перенаправляет зарегистрированным наблюдателям следующее уведомление:
NSManagedObjectContextDidSaveNotification
, следовательно, все, что вам нужно сделать, это:
1) в вашем основном потоке, возможно, в методе
viewDidLoad
, зарегистрируйте это уведомление:[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:nil];
2) реализуйте метод
contextDidSave:
в главном потоке следующим образом:- (void)contextDidSave:(NSNotification *)notification { SEL selector = @selector(mergeChangesFromContextDidSaveNotification:); [managedObjectContext performSelectorOnMainThread:selector withObject:notification waitUntilDone:YES]; }
3) в вашем
dealloc
метод добавить следующее:4) Создайте новый контекст в другом потоке, используя что-то вроде следующего метода:[[NSNotificationCenter defaultCenter] removeObserver:self];
5) при получении новых данных правильным способом обработки этой ситуации является использование идентификаторов управляемых объектов. Поскольку идентификаторы управляемых объектов потокобезопасны, их можно передавать из основного потока в другой поток, а затем использовать- (NSManagedObjectContext*)createNewManagedObjectContext { NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init]; [moc setPersistentStoreCoordinator:[self persistentStoreCoordinator]]; [moc setUndoManager:nil]; return [moc autorelease]; }
existingObjectWithID:error:
для извлечения объекта, связанного с определенным идентификатором, обновления его и сохранения контекста. Теперь слияние будет действовать следующим образом: вы ожидаете. Кроме того, если вы заранее не знаете, какие идентификаторы управляемых объектов должны передаваться между потоками, то в другом потоке вы просто извлекаете объекты, используя предикат, чтобы получить те, которые соответствуют объектам, полученным с сервера, затем вы обновляете их и сохраняете контекст.