У меня есть основанное на документе приложение Core Data (работающее в Mac OS X 10.5 и выше), где я пытаюсь использовать два NSManagedObjectContext
в главном потоке.Я хотел бы объединить изменения, сделанные во вторичном контексте, с моим основным (основным) контекстом.Кроме того, я хочу, чтобы изменения, которые были объединены из вторичного контекста, были отменены и чтобы документ был помечен как «грязный».Я думаю, мой вопрос похож на « Отмена вставки базовых данных, которые выполняются из основного потока », но, ATM, я не использую другие потоки.
Я наблюдал заNSManagedObjectContextDidSaveNotification
(который отправляется из второго контекста при вызове -[self.secondaryContext save:]
) следующим образом:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(mocDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:self.secondaryContext];
В методе -mocDidSave:
, вызванном наблюдателем, я пытался использовать -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:]
в основном контекстечтобы объединить изменения из вторичного контекста в первичный контекст:
- (void)mocDidSave:(NSNotification *)notification
{
[self.primaryContext mergeChangesFromContextDidSaveNotification:notification];
}
Однако, хотя, скажем, вставленные объекты легко появляются в моем контроллере массива, документ не помечен как грязный и свойство isInserted
для вновь добавленных управляемых объектов не установлено значение YES.Кроме того, вставка (в основной контекст) не отменяется.
Повторная ошибка любых вставленных объектов, по крайней мере, помечает документ как грязный, но вставка по-прежнему не отменяется:
- (void)mocDidSave:(NSNotification *)notification
{
[self.primaryContext mergeChangesFromContextDidSaveNotification:notification];
for (NSManagedObject *insertedObject in [[notification userInfo] objectForKey:NSInsertedObjectsKey]) {
[self.primaryContext refreshObject:[self.primaryContext existingObjectWithID:[insertedObject objectID] error:NULL] mergeChanges:NO];
}
}
Wrt-mocDidSave:
, у меня были несколько лучшие результаты с пользовательской реализацией:
- (void)mocDidSave:(NSNotification *)notification
{
NSDictionary *userInfo = [notification userInfo];
NSSet *insertedObjects = [userInfo objectForKey:NSInsertedObjectsKey];
if ([insertedObjects count]) {
NSMutableArray *newObjects = [NSMutableArray array];
NSManagedObject *newObject = nil;
for (NSManagedObject *insertedObject in insertedObjects) {
newObject = [self.primaryContext existingObjectWithID:[insertedObject objectID] error:NULL];
if (newObject) {
[self.primaryContext insertObject:newObject];
[newObjects addObject:newObject];
}
}
[self.primaryContext processPendingChanges];
for (NSManagedObject *newObject in newObjects) {
[self.primaryContext refreshObject:newObject mergeChanges:NO];
}
}
NSSet *updatedObjects = [userInfo objectForKey:NSUpdatedObjectsKey];
if ([updatedObjects count]) {
NSManagedObject *staleObject = nil;
for (NSManagedObject *updatedObject in updatedObjects) {
staleObject = [self.primaryContext objectRegisteredForID:[updatedObject objectID]];
if (staleObject) {
[self.primaryContext refreshObject:staleObject mergeChanges:NO];
}
}
}
NSSet *deletedObjects = [userInfo objectForKey:NSDeletedObjectsKey];
if ([deletedObjects count]) {
NSManagedObject *staleObject = nil;
for (NSManagedObject *deletedObject in deletedObjects) {
staleObject = [self.primaryContext objectRegisteredForID:[deletedObject objectID]];
if (staleObject) {
[self.primaryContext deleteObject:staleObject];
}
}
[self.primaryContext processPendingChanges];
}
}
Это приводит к обновлению контроллера массива, помечению документа как грязному, а вставки и удаления отменяются.Тем не менее, у меня все еще есть проблемы с обновлениями, которые еще нельзя отменить.Должен ли я вместо этого вручную зацикливать все обновленные объекты и использовать -[NSManagedObject changedValues]
для повторного применения изменений в первичном контексте?
Эта пользовательская реализация, конечно, дублирует большую часть работы из вторичного контекста в главном контексте.Есть ли другой / лучший способ получить слияние между двумя контекстами, сохраняя слияние как невыполнимый шаг?