2013-04-03 3 views
2

У меня есть интересная проблема, с которой я не могу найти решение - у меня есть два контекста управляемых объектов, «основной» и «резервный». «Главная» создается с помощью NSMainQueueConcurrencyType, а «поддержка» создается с помощью «NSPrivateQueueConcurrencyType». Кроме того, «backing» был установлен как родительский элемент main.NSManagedObjectContextDidSaveNotification merging and deletedObjects

Я хочу сделать (потенциально дорого) операции записи на MOC резервного копирования, а затем внести эти изменения (когда они завершены) в главный контекст и, таким образом, обновить пользовательский интерфейс из-за использования NSFetchedResultsController. Моя проблема заключается в следующем: кажется, что после вызова mergeChangesFromContextDidSaveNotification свойство deletedObjects на основном MOC заполняется всеми объектами, которые были удалены в фоновом режиме, используя резервную очередь.

В качестве примера, вот какой-то код.

[appDelegate.backingContext performBlock:^{ 

    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Parent"]; 
    NSArray *objects = [appDelegate.backingContext executeFetchRequest:fetchRequest error:nil]; 
    for(Parent *parent in objects) { 
     NSMutableOrderedSet *children = [parent mutableOrderedSetValueForKey:@"children"]; 
     for(Child *child in children) { 
      [appDelegate.backingContext deleteObject:child]; 
     } 
     [children removeAllObjects]; 

     for(int i=0;i<3;i++) { 
      Child *child = [NSEntityDescription insertNewObjectForEntityForName:@"Child" 
                 inManagedObjectContext:appDelegate.backingContext]; 
      child.name = [NSString stringWithFormat:@"Child #%i", i]; 
      [children addObject:child]; 
     } 
    } 

    [appDelegate.backingContext save:nil]; 
}]; 

и на моем приложение делегата

- (void)mergeContextChanges:(NSNotification *)notification { 
    [self.mainContext performBlock:^{ 
     NSLog(@"Before merge: updates - %i, inserts - %i, deletes - %i", 
      self.mainContext.updatedObjects.count, 
      self.mainContext.insertedObjects.count, 
      self.mainContext.deletedObjects.count); 
     [self.mainContext mergeChangesFromContextDidSaveNotification:notification]; 
     NSLog(@"After merge: updates - %i, inserts - %i, deletes - %i", 
      self.mainContext.updatedObjects.count, 
      self.mainContext.insertedObjects.count, 
      self.mainContext.deletedObjects.count); 
    }]; 
} 

Вот что говорит журнал после того, как изменения были объединены -

2013-04-03 00:51:40.476 CoreDataTest[41617:c07] Before merge: updates - 0, inserts - 0, deletes - 0 
2013-04-03 00:51:40.477 CoreDataTest[41617:c07] After merge: updates - 0, inserts - 0, deletes - 3 

Вы заметите, что основной контекст сообщает 3 объекта в ожидании для удаления. Насколько я могу судить, это неверно - не следует mergeContextChanges: заставить состояние контекста (в противном случае полностью нетронутого) не отображать ожидающие изменения? Суть этого метода заключается в том, что изменения уже были зафиксированы в постоянном хранилище.

Что мне здесь не хватает?

ответ

2

Документация mergeChangesFromContextDidSaveNotification: говорит:

Этот метод обновляет любые объекты, которые были обновлены в другом контексте, разломы в любых вновь введенных объектах, и вызывает DeleteObject: на тех, которые были удалены ,

который (как я его прочитал) согласуется с вашими результатами.

+1

Да, после немного более продуманного, это имеет смысл. Возможно, MOC не должен отмечать объект как ожидающее удаление, если он не перезапущен с MOC в первую очередь. Я могу понять, почему, если бы вы хотели это сделать, это может появиться в отношениях, или кто-то может иметь ссылку на него.Но если это полностью внутреннее состояние MOC, я не понимаю, почему он должен быть отмечен. – dpratt

+0

Вы когда-нибудь находили путь, поэтому слияние не вызывает флаг hasChanges ?. (Благодаря!) –

0

Эти объекты, вероятно, были получены (до их удаления) в основном контексте.
Поскольку ваш родитель mainContext является базой, вы можете зафиксировать эти изменения в родительском контексте (выполнить сохранение в mainContext).
Сохранение не должно занять много времени, поскольку оно не привязано к постоянному хранилищу, только к родительскому контексту.

Вы можете сохранить эти элементы в основном контексте до тех пор, пока он не будет сохранен другим потоком в вашем приложении.
Ваш пользовательский интерфейс ответит на удаление этих элементов.

+0

Единственный выбор, который я выполнил в приведенном выше примере, - это тот, который получает, удаляет и создает дочерние объекты в контексте поддержки. Я не понимаю, почему эти удаления отображаются как ожидающие изменения в пустом главном контексте. Кроме того, я не хочу, чтобы вам приходилось сохранять в основном контексте на регулярной основе - дело в том, что основной контекст предназначен только для чтения, а резервный - где я мутирую данные. – dpratt

Смежные вопросы