CoreData - 重复现有对象

Posted

技术标签:

【中文标题】CoreData - 重复现有对象【英文标题】:CoreData - Duplicate existing object 【发布时间】:2012-02-18 18:44:04 【问题描述】:

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

        movement2 = [NSEntityDescription
                                     insertNewObjectForEntityForName:@"Movement" 
                                     inManagedObjectContext:self.managedObjectContext];

        movement2.name = movement.name;
        movement2.value = movement.value;
        movement2.date = movement.date;
        ... 

它有效。但是……

有什么方法可以在一行代码中将movement 的所有值复制到movement2

【问题讨论】:

【参考方案1】:

NSManagedObject 与 NSObject 不同,它提供了一个 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];

更多详情请见the documentation。

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

【讨论】:

您可以使用结合了属性和关系的entity.propertiesByName。少一个 for 循环 ;) @Michael 天哪,我不知道我是怎么错过的,并用两个循环编写了很多助手!谢谢,我编辑了答案。【参考方案2】:

API 中没有复制NSManagedObjects 的方法,因为它们不符合NSCopying,也不符合NSCoding。这是有道理的,考虑到如果它具有关系,您通常不清楚如何复制这样的对象:它应该与相同的对象有关系,还是它们的副本?那些副本呢?这些是难题,其答案可能取决于关系的性质(对多或对一),因此取决于 Core Data 的特定用例。

这么简短的回答:我会在你的 sn-p 中做你正在做的事情,或者写一个方法来制作副本。看起来你的NSManagedObjects 只有简单的属性,没有关系,所以应该是直截了当的。

【讨论】:

【参考方案3】:

我为 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
    

【讨论】:

以上是关于CoreData - 重复现有对象的主要内容,如果未能解决你的问题,请参考以下文章

ios CoreData删除第n个对象[重复]

RestKit / CoreData:两次请求相同的URL时插入重复的对象而不是合并

CoreData:第 0 行没有现有条目,但第 1、2、3 行没有现有条目

如何使用CoreData获取相关实体的对象?

将 CoreData 添加到现有项目后出错

保存期间CoreData比较错误