Я имею то, что я принимаю, довольно стандартная установка, с одним 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 и вручную скопировать каждую пару "ключ-значение" со старого объекта, но я не очень доволен тем решением. (У меня есть много различных управляемых объектов, для которых у меня есть эта проблема, таким образом, я не хочу должным быть писать и обновлять копию: методы для всех них, в то время как я продолжаю разрабатывать.) Там лучший путь?
Во-первых, наличие более одного NSManagedObjectContext
на одном потоке - это не стандартная конфигурация. В 99% случаев вам нужен только один контекст, и это решит эту ситуацию для вас.
Почему вы считаете, что вам нужно более одного NSManagedObjectContext
?
Это действительно один из немногих случаев использования, которые я видел, где это имеет смысл. Для этого необходимо выполнить рекурсивное копирование объекта из одного контекста в другой. Рабочий процесс будет выглядеть следующим образом:
-dictionaryWithValuesForKeys
и -[NSEntityDescription attributesByName]
). -setValuesForKeysWithDictionary
)-[NSEntityDescription relationsByName]
Как уже упоминалось, вы можете скачать пример кода из моей книги The Pragmatic Programmers Core Data Book и посмотреть одно из решений этой проблемы. Конечно, в книге я обсуждаю это более подробно :)
.Документация вводит в заблуждение и является неполной. Методы objectID сами по себе не копируют объекты, они просто гарантируют, что вы получили именно тот объект, который хотели.
context2
в примере на самом деле является исходным контекстом, а не конечным. Вы получаете nil, потому что в контексте назначения нет объекта с таким идентификатором.
Копирование управляемых объектов является довольно сложной задачей из-за сложности графа объектов и способа, которым контекст управляет этим графом. Вам действительно придется подробно воссоздать скопированный объект в новом контексте.
Вот несколько примеров кода, которые я вырезал из примера кода для The Pragmatic Programmer's Core Data: Apple's API for Persisting Data on Mac OS X. (Возможно, вы сможете загрузить весь код проекта без покупки книги на сайте Pragmatic). Это должно дать вам примерное представление о том, как копировать объект между контекстами.
Вы можете создать некоторый базовый код, который копирует объекты, но особенности отношений каждого графа объектов обычно означают, что вы должны адаптировать его для каждой модели данных.
Вам необходимо убедитесь, что вы сохраняете контекст, в котором находится managedObject
. Чтобы получить тот же объект в другом контексте, он должен присутствовать в постоянном хранилище.
Согласно документации , objectWithID:
всегда возвращает объект. Таким образом, тот факт, что ошибка разрешается в объекте со всеми значениями nil
, означает, что он не находит ваш объект в постоянном хранилище.