Как я могу продублировать или скопировать Базовый Управляемый Объект Данных? - PullRequest
53 голосов
/ 28 апреля 2010

У меня есть управляемый объект («A»), который содержит различные атрибуты и типы отношений, и его отношения также имеют свои собственные атрибуты и отношения. То, что я хотел бы сделать, это «скопировать» или «продублировать» весь граф объекта, укорененный в объекте «A», и, таким образом, создать новый объект «B», который очень похож на «A».

Чтобы быть более точным, ни одно из отношений, содержащихся в «B» (или его дочерних элементах), не должно указывать на объекты, связанные с «A». Должен быть совершенно новый объектный граф с аналогичными неповрежденными отношениями, и все объекты, имеющие одинаковые атрибуты, но, конечно, разные идентификаторы.

Существует очевидный ручной способ сделать это, но я надеялся узнать о более простых способах сделать это, которые не были полностью очевидны из документации Core Data.

ТИА!

Ответы [ 15 ]

2 голосов
/ 28 апреля 2010

Это называется "глубокая копия". Поскольку он может быть на удивление дорогим, многие языки / библиотеки не поддерживают его «из коробки» и требуют, чтобы вы развернули его самостоятельно К сожалению, какао - один из них.

0 голосов
/ 26 июля 2018

Swift 4.0 версия

import UIKit
import CoreData

class ManagedObjectCloner: NSObject {

    static func cloneObject(source :NSManagedObject, context :NSManagedObjectContext) -> NSManagedObject{
        let entityName = source.entity.name
        let cloned = NSEntityDescription.insertNewObject(forEntityName: entityName!, into: context)

        let attributes = NSEntityDescription.entity(forEntityName: entityName!, in: context)?.attributesByName

        for (key,_) in attributes! {
            cloned.setValue(source.value(forKey: key), forKey: key)
        }

        let relationships = NSEntityDescription.entity(forEntityName: entityName!, in: context)?.relationshipsByName
        for (key,_) in relationships! {
            let sourceSet = source.mutableSetValue(forKey: key)
            let clonedSet = cloned.mutableSetValue(forKey: key)
            let e = sourceSet.objectEnumerator()

            var relatedObj = e.nextObject() as? NSManagedObject

            while ((relatedObj) != nil) {
                let clonedRelatedObject = ManagedObjectCloner.cloneObject(source: relatedObj!, context: context)
                clonedSet.add(clonedRelatedObject)
                relatedObj = e.nextObject() as? NSManagedObject
            }
        }

        return cloned
    }

}
0 голосов
/ 31 мая 2016

Мой взгляд на это в https://gist.github.com/jpmhouston/7958fceae9216f69178d4719a3492577

  • передает rel.inverseRelationship.name в рекурсивный метод, чтобы исключить посещение обратных связей, а не поддерживать набор alreadyCopied объектов

  • мелкие или глубокие копии

  • принимает ключевые пути отношений с не клоном, но для того, чтобы либо пропустить, либо просто скопировать, если обратное является отношением ко многим

  • Обходной путь для упорядоченных, ко-многим отношений, заканчивающихся в обратном порядке - просто итерируйте по исходным объектам в обратном направлении :) Я не уверен, хорошая ли это идея или она вообще работает все время

Обратная связь и комментарии приветствуются, особенно если кто-то может уточнить комментарий Benjohn о неправильном заказе выше" Обходной путь для этого состоит в том, чтобы построить полный заказанный установить, а затем назначить, используя примитивный вариант KVO.", и можно улучшить мой заказной, для многих обходной путь.

Кроме того, я использую MagicalRecord, и поэтому мой код предполагает это, включая предоставление простых методов, использующих его контекст по умолчанию.

0 голосов
/ 20 февраля 2015

Если вы хотите связать только сущности в иерархии отношений, вам нужно только добавить следующий код к решению Дмитрия

Между этим

NSString *entityName = [[self entity] name];

ЗДЕСЬ if ([namesOfEntitiesToExclude includesObject: entityName]) {

NSMutableArray *arrayToOnlyRelate   = [NSMutableArray arrayWithObjects:@"ENTITY 1",@"ENTITY 2",@"ENTITY 3", nil];

if ([arrayToOnlyRelate containsObject:entityName]) {
    return self;
}
0 голосов
/ 31 августа 2010

Также:

[clone setValuesForKeysWithDictionary:[item dictionaryWithValuesForKeys:[properties allKeys]]];
[clone setValuesForKeysWithDictionary:[item dictionaryWithValuesForKeys:[attributes allKeys]]];
...