更新旧对象时,核心数据会创建一个新对象

时间:2019-05-28 16:15:35

标签: ios swift core-data

首先,我不认为这是重复的:Updating object value in core data is also creating a new object(在Obj-C中,他们每次定罪时都在调用insertNewObject。)

背景信息:我从Ray Wenderlich的书中学到了如何使用CoreData,并在编写此代码时引用了它。如果您有这本书,我会按照第3章中的概述滚动我自己的定制堆栈。如果需要,我可以显示此代码。

队列是我要更​​新的实体。

它具有1个属性:name-String

和1对多关系:任务:任务enter image description here enter image description here enter image description here 我的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)")
        }

    }
}

为了节省空间,我不会为我尝试过的其他事情添加代码。

  • 我尝试使用查找/创建功能并在该方法中进行更新。
  • 我尝试将队列另存为本地对象,并将其传递给也会导致重复的addTask函数。
  • 是否传递任务或在addTask函数中创建一个都没关系。

我开始相信我的问题是我的dataModel文件中的某种原因导致的,因为我已经在线尝试了许多“如何更新核心数据对象”教程,每次都得到相同的结果。

每当我尝试更新对象时,都会调用

awakeFromInsert()。不知道这是否应该发生。

在我的应用程序的其他地方,更新工作正常。例如,如果我将“子任务”添加到“任务”。工作正常。但是,如果我想更改另一个名为Project的实体的名称,则该对象重复。 (项目具有一个获取的id属性,然后更改了name属性。)

先谢谢您。我已经把头发拉了好几个小时了。

1 个答案:

答案 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,这是故意的吗?