как я могу скопировать или переместить nsmanagedobject из одного контекста в другой?

<p>у меня есть то, что я предполагаю, является довольно стандартной установкой, с одним moc блокнота, который никогда не сохраняется (содержащий кучу объектов, загруженных из интернета), и другим постоянным moc, который сохраняет объекты. когда пользователь выбирает объект из scratchmoc для добавления в свою библиотеку, я хочу либо 1) удалить объект из scratchmoc и вставить его в перманентный moc, либо 2) скопировать объект в перманентный moc. <a href="http://developer.apple.com/mac/library/documentation/cocoa/conceptual/coredata/articles/cdfaq.html">core data faq</a> говорит, что я могу скопировать объект следующим образом:</p><pre><code>nsmanagedobjectid *objectid = [managedobject objectid]; nsmanagedobject *copy = [context2 objectwithid:objectid]; </code></pre><p>(в этом случае context2 будет перманентным moc.) однако, когда я делаю это, копируемый объект неисправен; данные изначально неразрешены. когда это действительно разрешено, позже все значения равны нулю; никакие данные (атрибуты или отношения) из исходного управляемого объекта не копируются и не ссылаются на них. поэтому я не вижу никакой разницы между использованием этого objectwithid: метода и просто вставкой совершенно нового объекта в constantmoc с использованием insertnewobjectforentityforname :.</p><p>я понимаю, что могу создать новый объект в перманентном мок и вручную скопировать каждую пару ключ-значение из старого объекта, но я не очень доволен этим решением. (у меня есть несколько различных управляемых объектов, для которых у меня есть эта проблема, поэтому я не хочу писать и обновлять методы copy: для всех из них, поскольку я продолжаю разрабатывать.) есть ли лучший способ?</p>

<p>во-первых, наличие более одного <code>nsmanagedobjectcontext</code> в одном потоке <strong> не является </strong> стандартной конфигурацией. в 99% случаев вам нужен только один контекст, и это решит эту ситуацию для вас.</p><p>почему вы считаете, что вам нужно более одного <code>nsmanagedobjectcontext</code>?</p><h2>обновление</h2><p>это на самом деле один из немногих случаев использования, которые я видел, где это имеет смысл. для этого вам нужно сделать рекурсивную копию объекта из одного контекста в другой. рабочий процесс будет следующим:</p><ol> <li>создать новый объект в постоянном контексте</li> <li>получить словарь атрибутов из исходного объекта (используйте <code>-dictionarywithvaluesforkeys</code> и <code>-[nsentitydescription attributesbyname]</code> для этого.</li> <li>установить словарь значений на целевой объект (используя <code>-setvaluesforkeyswithdictionary</code>)</li> <li>если у вас есть отношения, вам нужно будет делать эту копию рекурсивно и обходить отношения либо жестко закодировано (чтобы избежать некоторой циклической логики), либо с помощью <code>-[nsentitydescription relationshipsbyname]</code></li> </ol><p>как уже упоминалось, вы можете загрузить пример кода из моей книги из <a href="http://www.pragprog.com/titles/mzcd/core-data">базовая книга данных программистов pragmatic</a> и увидеть одно решение этой проблемы. конечно, в книге я обсуждаю это более подробно :)</p>

<p>документация вводит в заблуждение и неполна. методы objectid сами по себе не копируют объекты, они просто гарантируют, что вы получили нужный объект.</p><p>фактически <code>context2</code> в этом примере является исходным контекстом, а не местом назначения. вы получаете ноль, потому что целевой контекст не имеет объекта с этим идентификатором.</p><p>копирование управляемых объектов довольно сложное из-за сложности графа объектов и способа управления графом контекстом. вы должны воссоздать скопированный объект подробно в новом контексте.</p><p> <a href="http://pastebin.com/efkji4sy">вот пример кода</a> , который я вырвал из кода примера для <a href="http://www.pragprog.com/titles/mzcd/core-data">основные данные прагматического программиста <em>: api apple для хранения данных в mac os x </em></a> . (возможно, вы сможете загрузить весь код проекта, не покупая книгу на сайте pragmatic.) она должна дать вам приблизительное представление о том, как выполнить копирование объекта между контекстами.</p><p>вы можете создать некоторый базовый код, который копирует объекты, но особенности отношений каждого графа объекта обычно означают, что вам нужно настроить для каждой модели данных.</p>

<p>у меня была такая же проблема, и я нашел эту статью о созданных отключенных объектах, которые впоследствии можно было добавить в контекст: <a href="http://locassa.com/temporary-storage-in-apples-coredata/">http://locassa.com/teilitary-storage-in-apples-coredata/</a> </p><p>идея в том, что у вас есть nsmanagedobject, потому что вы собираетесь хранить объекты в базе данных. мое препятствие состояло в том, что многие из этих объектов загружаются через http api, и я хочу выбросить большинство из них в конце сеанса. подумайте о потоке пользовательских сообщений, и я хочу сохранить только те, которые были добавлены в избранное или сохранены как черновик.</p><p>я создаю все свои сообщения, используя</p><pre><code>+ (id)newpost { nsentitydescription *entitydescription = [nsentitydescription entityforname:@"post" inmanagedobjectcontext:self.managedobjectcontext]; post *post = [[post alloc] initwithentity:entitydescription insertintomanagedobjectcontext:nil]; return post; } </code></pre><p>а затем сообщения вставляются в локальный контекст управляемого объекта, когда они предпочтительны</p><pre><code>+ (bool)favoritepost:(post *)post isfavorite:(bool)isfavorite { // set the post's isfavorite flag post.isfavorite = [nsnumber numberwithbool:isfavorite]; // if the post is being favorited and not yet in the local database, add it nserror *error; if (isfavorite && [self.managedobjectcontext existingobjectwithid:post.objectid error:&error] == nil) { [self.managedobjectcontext insertobject:post]; } // else if the post is being un-favorited and is in the local database, delete it else if (!isfavorite && [self.managedobjectcontext existingobjectwithid:post.objectid error:&error] != nil) { [self.managedobjectcontext deleteobject:post]; } // if there was an error, output and return no to indicate a failure if (error) { nslog(@"error: %@", error); return no; } return yes; } </code></pre><p>надеюсь, это поможет.</p>

<p>вам необходимо убедиться, что вы сохраняете контекст, в котором находится <code>managedobject</code>. чтобы извлечь тот же объект в другом контексте, он должен присутствовать в постоянном хранилище.</p><p>согласно <a href="http://developer.apple.com/mac/library/documentation/cocoa/reference/coredataframework/classes/nsmanagedobjectcontext\_class/nsmanagedobjectcontext.html#//apple\_ref/doc/uid/tp30001182-bajifiga">документация</a> , <code>objectwithid:</code> всегда возвращает объект. таким образом, тот факт, что ошибка разрешается для объекта, будет иметь все значения <code>nil</code>, что означает, что он не находит ваш объект в постоянном хранилище.</p>