CoreData – 复制现有对象

您想从我的核心数据db复制一个对象。 现在我正在使用

movement2 = [NSEntityDescription insertNewObjectForEntityForName:@"Movement" inManagedObjectContext:self.managedObjectContext]; movement2.name = movement.name; movement2.value = movement.value; movement2.date = movement.date; ... 

它的工作原理。 但…

有没有办法在一行代码中将所有movement值复制到movement2

与NSObject不同,NSManagedObject提供了一个API来迭代其属性和关系。 或者说,它是实体描述。 不过,它不是一个单行。

 movement2 = [NSEntityDescription insertNewObjectForEntityForName:@"Movement" inManagedObjectContext:self.managedObjectContext]; NSEntityDescription *entity = [movement entity]; for (NSString *propertyName in [entity propertiesByName]) { [movement2 setValue:[movement valueForKey:propertyName] forKey:propertyName]; } 

有关详细信息,请参阅文档 。

这足以克隆大多数对象。 如果数据库结构正确,那么以这种方式复制关系,它们的反向关系也会更新。 因此,如果您的Movement与MovementDirection有关系,并且MovementDirection具有反向1对多关系parentMovements ,则在您调用上面的代码后,此parentMovements集将同时包含movementmovement2

API中没有复制NSManagedObjects ,因为它们不符合NSCopying ,也不符合NSCoding 。 这是有道理的,因为如果它有关系,你通常不清楚如何复制这样的对象:它应该与相同的对象有关系,还是它们的副本? 这些副本怎么样? 这些是难题,其答案可能取决于关系的性质(对多或一对),因此也取决于核心数据的具体用例。

如此简短的回答:我会在你的片段中做你正在做的事情,或者写一个方法来制作副本。 看起来你的NSManagedObject只有简单的属性而且没有关系,因此它应该是直截了当的。

我为NSManagedObject做了一个基本的重复扩展(基于@ coverback的回答)。 小心使用(虽然对我来说它迄今为止有效)

斯威夫特4:

 enum CopyBehavior { case none, copy, deepcopy } extension NSManagedObject { func duplicate(only: [String]) -> NSManagedObject { return duplicate { only.contains($0) ? .copy : .none } } func duplicate(except: [String], deep: [String] = []) -> NSManagedObject { return duplicate { deep.contains($0) ? .deepcopy : except.contains($0) ? .none : .copy } } func duplicate(byProperties fun: (String) -> CopyBehavior) -> NSManagedObject { let duplicate = NSEntityDescription.insertNewObject(forEntityName: entity.name!, into: managedObjectContext!) for propertyName in entity.propertiesByName.keys { switch fun(propertyName) { case .copy: let value = self.value(forKey: propertyName) duplicate.setValue(value, forKey: propertyName) case .deepcopy: let value = self.value(forKey: propertyName) if let value = value as? NSSet { let copy = value.map { return ($0 as! NSManagedObject).duplicate(byProperties: fun) } duplicate.setValue(copy, forKey: propertyName) } else if let value = value as? NSOrderedSet { let copy = value.map { return ($0 as! NSManagedObject).duplicate(byProperties: fun) } duplicate.setValue(NSOrderedSet(array: copy), forKey: propertyName) } else if let value = value as? NSManagedObject { let copy = value.duplicate(byProperties: fun) duplicate.setValue(copy, forKey: propertyName) } else { fatalError("Unrecognized deepcopy attribute!") } case .none: break } } return duplicate } }