Дублирование сущности, когда изменения, сделанные дочерним элементом ManagedObjectContext, передаются (сохраняются) к его родителю - PullRequest
5 голосов
/ 10 марта 2012

Я ожидаю (даже надеюсь), что это будет глупый вопрос, но после многочасовой борьбы с этой проблемой мне нужно некоторое понимание.

Мое приложение iOS 5.1 использует вложенные MOC, имеющие дочерний MOC PrivateQueueConcurrency, назовите его MOC-Child, чьим родителем является MOC MainQueueConcurrency, назовите его MOC-Parent. MOC-Parent поддерживает табличное представление, в котором отображаются его сущности.

MOC-Child используется синтаксическим анализатором, который асинхронно запускается в неосновном потоке, для создания новых сущностей, соответствующих описаниям XML-сущностей, проанализированных из соединения URL, а затем отправляет новые сущности в MOC-Parent. через сохранение на MOC-Child, которое отображает их в виде таблицы. Это прекрасно работает:

1) Parser creates entity in MOC-Child
2) Parser saves MOC-Child
3) New entity is added to MOC-Parent
4) New entity is displayed in MOC-Parent's table view

Однако описание любого данного объекта в этом фиде может со временем изменяться, поэтому описываемый объект должен быть изменен в приложении, а его ячейка в табличном представлении обновлена. Таким образом, для каждого описания объекта в фиде анализатор пытается извлечь объект (если есть) в MOC-Child, имеющий тот же идентификатор, что и у описанного объекта, и, если он есть, сравнивает значения существующего объекта со значениями описания в посмотрим, изменилось ли что-нибудь. Когда анализатор обнаруживает, таким образом, что объект был изменен, он обновляет значения существующего объекта в MOC-Child новыми значениями в описании, а затем сохраняет MOC-Child, чтобы передать изменения до MOC-Parent.

Здесь все идет не так. Я подумал, что изменения, внесенные в извлеченную сущность в MOC-Child, при передаче ее родителю путем его сохранения просто «появятся» в «той же» сущности в MOC-Parent. Тем не менее, я вижу, что измененный объект из MOC-Child добавляется к MOC-Parent, , как будто это совершенно отдельный и новый объект ; в результате MOC-Parent и, следовательно, табличное представление, к которому он обращается, в итоге получают две сущности для каждой измененной сущности:

1) Parser modifies existing entity in MOC-Child
2) Parser saves MOC-Child
3) Modified entity is _added to_ MOC-Parent
4) Entity is displayed _twice_ in MOC-Parent's table view

Что дает? Что мне нужно сделать, чтобы изменить значения существующего объекта в MOC-Parent, если я не могу сделать это в MOC-Child? И если я смогу сделать это в MOC-Child, что если мне нужно сделать что-то еще, кроме сохранения MOC-Child, чтобы получить изменения, которые будут сделаны в MOC-Parent, без добавления объекта во второй раз?

Заранее благодарим за любую помощь или понимание, которое вы можете предложить!

Карл

P.S. Пара уточнений. Когда я говорю, что измененный объект добавляется в MOC-Parent, я имею в виду, что NSFetchedResultsController, который отслеживает MOC-Parent, выдает NSFetchedResultsChangeInsert тип изменения ( не NSFetchedResultsChangeUpdate тип изменения) для измененного объекта, хотя «тот же» объект уже присутствует в MOC-Parent.

Кроме того, когда я говорю «та же» сущность, я имею в виду сущность в MOC-Parent, которая имеет тот же идентификатор, предоставленный описанием (в данном случае NSString), что и сущность, которая изменяется в MOC-потомке (не обязательно тот же objectID, на самом деле, очевидно, с другим objectId).

1 Ответ

1 голос
/ 14 февраля 2013

Я бы предположил, что, поскольку это такой старый вопрос, он больше не является проблемой.Но так как я недавно столкнулся с подобной ситуацией, я решил предложить свое решение.

Я загружаю массив из тысяч объектов (которые связаны одним или несколькими штрих-кодами) в файл XML,который я затем анализирую и сохраняю пакетами в фоновом контексте, используя подкласс NSOperation.Контекст диска (подключенный к постоянному хранилищу) прослушивает NSManagedObjectContextDidSaveNotification, после чего он также сохраняет (не забудьте сделать это в блоке).

[self.diskManagedObjectContext performBlockAndWait:^{
    NSError *error;
    if (![self.diskManagedObjectContext save:&error]) {
        NSLog(@"error saving to disk: %@",error);
    }
}];

Хитрая часть в том, что любой из этих объектов 'штрих-коды могут быть отсканированы (в контексте пользовательского интерфейса) до того, как файл XML будет полностью проанализирован и информация загружена в базу данных.И у меня есть табличное представление, поддерживаемое NSFetchedResultsController, которое отображает отсканированные объекты, которые показывают «неизвестные» в своих заголовках, пока данные не будут извлечены из фоновой загрузки.Как и в ситуации с Карлом, эти объекты должны быть обновлены при сохранении фонового контекста.

Чтобы справиться с этим, я использую трехконтекстную систему, аналогичную описанной в в этом вопросе , сКонтекст пользовательского интерфейса и фоновый контекст, оба из которых являются потомками моего основного дискового контекста (который привязан к постоянному хранилищу).Итак, во время синтаксического анализа XML я запускаю запрос на штрих-коды объекта в фоновом контексте (который также извлекается из контекста родительского диска), чтобы проверить, был ли объект уже создан с этим штрих-кодом.Если это так, я просто обновляю информацию, повторно сохраняю, сбрасываю контекст диска и вызываю refreshObject: mergeChanges: из контекста пользовательского интерфейса, чтобы извлечь эти изменения из контекста диска.Это успешно обновляет таблицу без создания дубликатов.

Первоначально я попробовал это, используя только два контекста, фоновый контекст и контекст пользовательского интерфейса, но, хотя я никогда не заканчивал создавать дублирующие объекты, я действительно хорошо повесил пользовательский интерфейснить.

Наверное, важный вопрос: как вы модифицируете существующую сущность?И не забудьте сброс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...