首先,我不认为这是重复的:Updating object value in core data is also creating a new object(在Obj-C中,他们每次定罪时都在调用insertNewObject。)
背景信息:我从Ray Wenderlich的书中学到了如何使用CoreData,并在编写此代码时引用了它。如果您有这本书,我会按照第3章中的概述滚动我自己的定制堆栈。如果需要,我可以显示此代码。
队列是我要更新的实体。
它具有1个属性:name-String
和1对多关系:任务:任务 我的CoreData逻辑位于包含managedContext的Struct中。
我有一个基本的查找/创建功能来创建Queue对象。这可行。它只会创建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)")
}
}
}
为了节省空间,我不会为我尝试过的其他事情添加代码。
我开始相信我的问题是我的dataModel文件中的某种原因导致的,因为我已经在线尝试了许多“如何更新核心数据对象”教程,每次都得到相同的结果。
每当我尝试更新对象时,都会调用awakeFromInsert()。不知道这是否应该发生。
在我的应用程序的其他地方,更新工作正常。例如,如果我将“子任务”添加到“任务”。工作正常。但是,如果我想更改另一个名为Project的实体的名称,则该对象重复。 (项目具有一个获取的id属性,然后更改了name属性。)
先谢谢您。我已经把头发拉了好几个小时了。
答案 0 :(得分: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,这是故意的吗?