2016-11-16 48 views
3

核心数据,自动更新导致问题的已更改对象,并使事情变得比需要的更混乱。如何制作核心数据对象的副本,保持不变

说我有这段代码:

let fetchRequest = Track.fetchRequest() 

//update it 
do { 
    let tracksFound = try self.managedObjectContext.fetch(fetchRequest) as! [Track] 
    print("retrieved") 

    let trackToUpdate = tracksFound[0] 

    trackToUpdate.locality = "please dont have updated" 

    do { 
     try self.managedObjectContext.save() 
     print("saved") 
    } 
    catch { 
     fatalCoreDataError(error) 
    } 

    for t in tracksFound { 
     print(t.locality) 
    } 
} 
catch { 
    fatalCoreDataError(error) 
} 

你可以看到它取一个[Track]对象数组,然后将其更新的第一要素适当localityplease dont have updated。然后它保存这个对象。最后它读取在开始时定义的tracksFound数组。我曾预期tracksFound保持不变,对象tracksFound[0].locality已更改为please dont have updated

如何阻止核心数据更新我的对象?我基本上想要制作一个tracksFound的副本,它将保持不变,所以我可以稍后将它用于决策。

感谢

+0

简单如果你没有调用save()方法的意思,你的对象将不会变化。 –

+0

代码'let trackToUpdate = tracksFound [0]'获取*引用*到该元素,而不是副本。因此,当你改变'trackToUpdate'时,你实际上正在改变'tracksFound [0]'。 – Michael

+0

@Karthick不,在这旁边很危险。 –

回答

2

正如迈克尔的评论中提到,trackToUpdate是的NSManagedObject实例的引用。指向同一对象的不同引用,...指向相同的对象。所以没有办法改变一个物体而不改变另一个物体,因为没有其他物体。 Swift通过意图混淆了引用,谁拥有那真的,真正高明的想法。

正如你所说,你必须创建一个副本。 NSManagedObject没有实现NSCopying协议。有很好的理由:如果实例引用其他实例(关系),则必须决定是否复制它们。这样做会导致复制整个图形的危险。如果不这样做,可以让你回到原来的问题,你分享一个被引用的实例。你必须做出决定。

将属性复制到简单字典中可能会更好。请记住,创建一个新的实例,这成为对象图的一部分。这是一种代码味道(即使术语可能太难了),也不会有“短时间”的管理对象。

但是,您可以创建一个新实例。然后通过-entity获得对象的实体描述。实体说明有一个属性-properties,其中包含所有属性的列表。使用这个,你可以迭代源属性并将其存储到新实例中。由于Objective-C的键值编码,在运行时可以做到这一点。

+0

感谢您解释这一点! – toast