Как я копирую или перемещаю NSManagedObject от одного контекста до другого?

Я имею то, что я принимаю, довольно стандартная установка, с одним MOC временной памяти, который никогда не сохраняется (содержащий набор объектов, загруженных с сети) и другой постоянный MOC, который сохраняет объекты. Когда пользователь выбирает объект из scratchMOC, чтобы добавить к ее библиотеке, я хочу любому 1) удалите объект из scratchMOC и вставьте в permanentMOC, или 2) копия объект в permanentMOC. Базовый FAQ Данных говорит, что я могу скопировать объект как это:

NSManagedObjectID *objectID = [managedObject objectID];
NSManagedObject *copy = [context2 objectWithID:objectID];

(В этом случае context2 был бы permanentMOC.) Однако, когда я делаю это, скопированный объект дан сбой; данные первоначально не разрешены. Когда это действительно становится разрешенным, позже, все значения являются нолем; ни одни из данных (атрибуты или отношения) от исходного managedObject на самом деле не скопированы или сосланы. Поэтому я не вижу различия между использованием этого objectWithID: метод и просто вставка совершенно нового объекта в permanentMOC, использующий insertNewObjectForEntityForName:.

Я понимаю, что могу создать новый объект в permanentMOC и вручную скопировать каждую пару "ключ-значение" со старого объекта, но я не очень доволен тем решением. (У меня есть много различных управляемых объектов, для которых у меня есть эта проблема, таким образом, я не хочу должным быть писать и обновлять копию: методы для всех них, в то время как я продолжаю разрабатывать.) Там лучший путь?

52
задан Aeonaut 8 June 2010 в 04:10
поделиться

3 ответа

Во-первых, наличие более одного NSManagedObjectContext на одном потоке - это не стандартная конфигурация. В 99% случаев вам нужен только один контекст, и это решит эту ситуацию для вас.

Почему вы считаете, что вам нужно более одного NSManagedObjectContext?

Обновление

Это действительно один из немногих случаев использования, которые я видел, где это имеет смысл. Для этого необходимо выполнить рекурсивное копирование объекта из одного контекста в другой. Рабочий процесс будет выглядеть следующим образом:

  1. создать новый объект в постоянном контексте
  2. получить словарь атрибутов из исходного объекта (для этого используйте -dictionaryWithValuesForKeys и -[NSEntityDescription attributesByName]).
  3. установите словарь значений на целевой объект (используя -setValuesForKeysWithDictionary)
  4. Если у вас есть отношения, вам нужно будет сделать это копирование рекурсивно и провести отношения либо жестко закодированными (чтобы избежать некоторой круговой логики), либо с помощью -[NSEntityDescription relationsByName]

Как уже упоминалось, вы можете скачать пример кода из моей книги The Pragmatic Programmers Core Data Book и посмотреть одно из решений этой проблемы. Конечно, в книге я обсуждаю это более подробно :)

.
53
ответ дан 7 November 2019 в 09:30
поделиться

Документация вводит в заблуждение и является неполной. Методы objectID сами по себе не копируют объекты, они просто гарантируют, что вы получили именно тот объект, который хотели.

context2 в примере на самом деле является исходным контекстом, а не конечным. Вы получаете nil, потому что в контексте назначения нет объекта с таким идентификатором.

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

Вот несколько примеров кода, которые я вырезал из примера кода для The Pragmatic Programmer's Core Data: Apple's API for Persisting Data on Mac OS X. (Возможно, вы сможете загрузить весь код проекта без покупки книги на сайте Pragmatic). Это должно дать вам примерное представление о том, как копировать объект между контекстами.

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

9
ответ дан 7 November 2019 в 09:30
поделиться

Вам необходимо убедитесь, что вы сохраняете контекст, в котором находится managedObject . Чтобы получить тот же объект в другом контексте, он должен присутствовать в постоянном хранилище.

Согласно документации , objectWithID: всегда возвращает объект. Таким образом, тот факт, что ошибка разрешается в объекте со всеми значениями nil , означает, что он не находит ваш объект в постоянном хранилище.

1
ответ дан 7 November 2019 в 09:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: