简体   繁体   English

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

[英]Core Data Creates A New Object When Updating An Old One

To start with, I don't believe this is a duplicate of: Updating object value in core data is also creating a new object (It's in Obj-C and they were calling insertNewObject every time they segued.) 首先,我不认为这是重复的: 更新核心数据中的对象值也将创建一个新对象 (在Obj-C中,并且他们每次定婚时都会调用insertNewObject。)

Background Info: I learned how to use CoreData from the Ray Wenderlich book and referred to it when writing this code. 背景信息:我从Ray Wenderlich的书中学习了如何使用CoreData,并在编写此代码时引用了它。 I rolled my own custom stack as outlined in Chapter 3 if you have the book. 如果您有这本书,我会按照第3章中的概述滚动我自己的自定义堆栈。 I can show the code for this if needed. 如果需要,我可以显示此代码。

Queue is the Entity I'm trying to update. 队列是我要更​​新的实体。

It has 1 property: name - String 它具有1个属性:name-String

And 1 to-many relationship: tasks: Task 与一对多的关系:任务:任务 在此处输入图片说明 在此处输入图片说明 在此处输入图片说明 My CoreData logic is in a Struct which contains the managedContext. 我的CoreData逻辑在包含managedContext的Struct中。

I have a basic find/create function to create a Queue object. 我有一个基本的查找/创建函数来创建Queue对象。 This works. 这可行。 It creates 1 and only 1 object. 它仅创建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
}

(As you can see by the queue.name suffix number I have tried a lot of different things.) (从queue.name后缀号可以看到,我尝试了很多不同的方法。)

I have tried just about everything I can think of: 我已经尝试了几乎所有我能想到的:

This code is basically copy/pasted from: How do you update a CoreData entry that has already been saved in Swift? 这段代码基本上是从以下位置复制/粘贴的: 如何更新已保存在Swift中的CoreData条目?

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)")
        }


}

Which causes a second Queue object to be created with the "Queue32" name. 这将导致使用“ Queue32”名称创建第二个Queue对象。

Here is another thing I tried: 这是我尝试过的另一件事:

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)")
        }

    }
}

For the sake of space I won't add code for other things I've tried. 为了节省空间,我不会为其他尝试添加的代码。

  • I've tried using the find/create function and updating in that method. 我尝试使用查找/创建功能并在该方法中进行更新。
  • I've tried saving the queue as a local object and passing it to the addTask function which causes duplication as well. 我尝试将队列另存为本地对象,并将其传递给也会导致重复的addTask函数。
  • It also doesn't matter if I pass in the Task or create one in the addTask function. 我传入Task还是在addTask函数中创建一个都无关紧要。

I am starting to believe my issue is something in my dataModel file causing this as I've tried a number of 'How to update a Core Data object' tutorials online and I get the same result each time. 我开始相信我的问题是我的dataModel文件中的某种原因引起的,因为我在线尝试了许多“如何更新核心数据对象”教程,每次都得到相同的结果。

awakeFromInsert() is called whenever I try to update an object. 每当我尝试更新对象时,都会调用awakeFromInsert()。 Not sure if this should be happening. 不知道这是否应该发生。

In other places in my app updating works. 在我的应用程序中的其他地方,更新工作正常。 For example, if I add a Subtask to a Task. 例如,如果我将“子任务”添加到“任务”。 It works fine. 工作正常。 However, if I want to change the name of another entity called Project the object duplicates. 但是,如果我想更改另一个名为Project的实体的名称,则该对象重复。 (Project has an id attribute which is fetched, then the name attribute is changed.) (项目具有一个获取的id属性,然后更改了name属性。)

Thank you in advance. 先感谢您。 I've been pulling my hair out for hours. 我已经把头发拉了好几个小时了。

I admit not having read all of your code but if you create a new managed object like this 我承认没有阅读所有代码,但是如果您创建了这样的新托管对象

let queue = Queue(context: managedContext)

then it will be added to the managedContext and will be saved to disk at some point. 然后将其添加到managedContext并在某些时候将其保存到磁盘。 So this code 所以这段代码

if results.count > 0 {
    return results.first!
} else {
    try managedContext.save()
}

is irrelevant in regard to the queue object created earlier because it will be saved even if results.count is > 0, although at a later point. 与先前创建的queue对象无关,因为即使results.count > 0,也将保存它,尽管稍后会保存。 So this means you will have to delete queue when the fetch is successful which feels unnecessary, better to wait with creating it 因此,这意味着您在成功获取数据后将不得不删除queue ,感觉这是不必要的,最好等待创建queue

if results.count > 0 {
    return results.first!
} else {
    let queue = Queue(context: managedContext)
    queue.name = "Queue32"
    try managedContext.save()
}

Off topic but I see you return nil if a new object was created rather than fetched, is this intended? 脱离主题,但我看到如果创建了一个新对象而不是获取了一个新对象,您将返回nil,这是故意的吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM