Core Data 在更新旧对象时创建一个新对象
Posted
技术标签:
【中文标题】Core Data 在更新旧对象时创建一个新对象【英文标题】:Core Data Creates A New Object When Updating An Old One 【发布时间】:2019-05-28 16:15:35 【问题描述】:首先,我不相信这是重复的:Updating object value in core data is also creating a new object(它在 Obj-C 中,他们每次 segued 时都会调用 insertNewObject。)
背景信息:我从 Ray Wenderlich 的书中学习了如何使用 CoreData,并在编写此代码时参考了它。如果你有这本书,我会按照第 3 章中的概述推出我自己的自定义堆栈。如果需要,我可以显示此代码。
队列是我要更新的实体。
它有 1 个属性:名称 - 字符串
还有一对多的关系:任务:任务 我的 CoreData 逻辑位于包含 managedContext 的 Struct 中。
我有一个基本的查找/创建函数来创建队列对象。这行得通。它创建 1 个且仅 1 个对象。
func findOrCreateMainQueue() -> Queue?
let queue = Queue(context: managedContext)
queue.name = "Queue32"
let queueFetch: NSFetchRequest<Queue> = Queue.fetchRequest()
queueFetch.predicate = NSPredicate(format: "%K == %@", #keyPath(Queue.name), "Queue32" as CVarArg)
do
let results = try managedContext.fetch(queueFetch)
print(results.count)
if results.count > 0
return results.first!
else
try managedContext.save()
catch let error as NSError
print("Fetch error: \(error) description: \(error.userInfo)")
return nil
(从 queue.name 后缀数字可以看出,我尝试了很多不同的方法。)
我已经尝试了所有我能想到的:
这段代码基本上是复制/粘贴自:How do you update a CoreData entry that has already been saved in Swift?
func addTaskToMainQueue2(task: Task)
let queueFetch: NSFetchRequest<Queue> = Queue.fetchRequest()
queueFetch.predicate = NSPredicate(format: "%K == %@", #keyPath(Queue.name), "Queue32" as CVarArg)
do
let results = try managedContext.fetch(queueFetch)
print(results.count)
if results.count > 0
var tasks = results[0].tasks?.mutableCopy() as? NSMutableOrderedSet
tasks?.add(task)
results[0].setValue(tasks, forKey: "tasks")
catch let error as NSError
print("Fetch error: \(error) description: \(error.userInfo)")
do
try managedContext.save()
catch let error as NSError
print("Save error: \(error),description: \(error.localizedDescription)")
这会导致使用“Queue32”名称创建第二个 Queue 对象。
这是我尝试的另一件事:
func addTaskToMainQueue(task: Task)
if var queue = findOrCreateMainQueue()
var tasks = queue.tasks?.mutableCopy() as? NSMutableOrderedSet
tasks?.add(task)
queue.tasks = tasks
do
try managedContext.save()
catch let error as NSError
print("Save error: \(error),description: \(error.localizedDescription)")
为了篇幅,我不会为我尝试过的其他事情添加代码。
我尝试过使用查找/创建功能并在该方法中进行更新。 我尝试将队列保存为本地对象并将其传递给 addTask 函数,这也会导致重复。 我是传入Task还是在addTask函数中创建一个也没关系。我开始相信我的问题出在我的 dataModel 文件中,因为我尝试了许多在线“如何更新核心数据对象”教程,但每次都得到相同的结果。
每当我尝试更新对象时,都会调用awakeFromInsert()。不确定这是否应该发生。
在我的应用更新工作的其他地方。例如,如果我将子任务添加到任务。它工作正常。但是,如果我想更改另一个名为 Project 的实体的名称,则该对象会重复。 (项目有一个 id 属性被获取,然后 name 属性被改变。)
提前谢谢你。我已经把头发拉了好几个小时了。
【问题讨论】:
【参考方案1】:我承认没有阅读您的所有代码,但如果您创建一个像这样的新托管对象
let queue = Queue(context: managedContext)
然后它将被添加到managedContext
并在某个时候保存到磁盘。所以这段代码
if results.count > 0
return results.first!
else
try managedContext.save()
与之前创建的queue
对象无关,因为即使results.count
> 0,它也会被保存,尽管稍后会保存。所以这意味着你必须在获取成功时删除queue
,这感觉没有必要,最好等待创建它
if results.count > 0
return results.first!
else
let queue = Queue(context: managedContext)
queue.name = "Queue32"
try managedContext.save()
题外话,但我看到如果创建了新对象而不是获取了新对象,则返回 nil,这是故意的吗?
【讨论】:
非常感谢。我假设当函数没有调用 save() 时删除了“队列”值。以上是关于Core Data 在更新旧对象时创建一个新对象的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI + Core Data - 更新对象(Detail -> DetailEdit)