提问者:小点点

IOS/SWIFT核心数据合并冲突


为了更新核心数据中的数据(当核心数据中已经有数据时),我删除了所有数据,然后重新插入数据。但我不知道为什么会发生合并冲突。我对核心数据还不熟悉,所以我也搞不清楚它到底出了什么问题。我想我需要更改我的deleteAll函数,但我不知道该更改什么。

代码如下。

Could not merge changes.
Error Domain=NSCocoaErrorDomain Code=133020 "Could not merge changes." UserInfo={conflictList=(
    "NSMergeConflict (0x6000008fdd00) for NSManagedObject (0x600003e80e60) with objectID '0x95773100e3922989 <x-coredata://60FADEF9-22B4-46FC-B17C-2B722FE843F7/Languages/p79417>' with oldVersion = 1 and newVersion = <deleted> and old object snapshot = {\n    code = es;\n    icon = spain;\n    isChecked = 0;\n    title = Spanish;\n}",
    "NSMergeConflict (0x6000008fda00) for NSManagedObject (0x600003e80aa0) with objectID '0x95773100e2722989 <x-coredata://60FADEF9-22B4-46FC-B17C-2B722FE843F7/Languages/p79414>' with oldVersion = 1 and newVersion = <deleted> and old object snapshot = {\n    code = fr;\n    icon = france;\n    isChecked = 1;\n    title = French;\n}",
    "NSMergeConflict (0x6000008fdbc0) for NSManagedObject (0x600003e80cd0) with objectID '0x95773100e3322989 <x-coredata://60FADEF9-22B4-46FC-B17C-2B722FE843F7/Languages/p79420>' with oldVersion = 1 and newVersion = <deleted> and old object snapshot = {\n    code = cn;\n    icon = china;\n    isChecked = 0;\n    title = Chineses;\n}",
    "NSMergeConflict (0x6000008fdd80) for NSManagedObject (0x600003e80d20) with objectID '0x95773100e3d22989 <x-coredata://60FADEF9-22B4-46FC-B17C-2B722FE843F7/Languages/p79419>' with oldVersion = 1 and newVersion = <deleted> and old object snapshot = {\n    code = kr;\n    icon = \"south-korea\";\n    isChecked = 0;\n    title = Korean;\n}",
    "NSMergeConflict (0x6000008fdc80) for NSManagedObject (0x600003e80b40) with objectID '0x95773100e2122989 <x-coredata://60FADEF9-22B4-46FC-B17C-2B722FE843F7/Languages/p79413>' with oldVersion = 1 and newVersion = <deleted> and old object snapshot = {\n    code = us;\n    icon = \"united-states-of-america\";\n    isChecked = 1;\n    title = English;\n}",
    "NSMergeConflict (0x6000008fddc0) for NSManagedObject (0x600003e80dc0) with objectID '0x95773100e3f22989 <x-coredata://60FADEF9-22B4-46FC-B17C-2B722FE843F7/Languages/p79418>' with oldVersion = 1 and newVersion = <deleted> and old object snapshot = {\n    code = jp;\n    icon = japan;\n    isChecked = 0;\n    title = Japanese;\n}",
    "NSMergeConflict (0x6000008fdb80) for NSManagedObject (0x600003e809b0) with objectID '0x95773100e2522989 <x-coredata://60FADEF9-22B4-46FC-B17C-2B722FE843F7/Languages/p79415>' with oldVersion = 1 and newVersion = <deleted> and old object snapshot = {\n    code = ru;\n    icon = russia;\n    isChecked = 1;\n    title = Russian;\n}",
    "NSMergeConflict (0x6000008fda40) for NSManagedObject (0x600003e801e0) with objectID '0x95773100e3b22989 <x-coredata://60FADEF9-22B4-46FC-B17C-2B722FE843F7/Languages/p79416>' with oldVersion = 1 and newVersion = <deleted> and old object snapshot = {\n    code = it;\n    icon = italy;\n    isChecked = 1;\n    title = Italien;\n}"
), NSExceptionOmitCallstacks=true}
private var persistenceManager = PersistenceManager.shared
private let request: NSFetchRequest<Languages> = Languages.fetchRequest()
private var coreDataLanguages: [Languages]

..

persistenceManager.deleteAll(request: request)
coreDataLanguages.forEach { language in    
    let language = Setting(isChecked: language.isChecked, title: language.title!, code: language.code!, icon: language.icon!)
    persistenceManager.insertLanguage(language: language)
}
class PersistenceManager {
    
    static var shared: PersistenceManager = PersistenceManager()
    
    var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "Setting")
        
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()
    
    var context: NSManagedObjectContext {
        return self.persistentContainer.viewContext
    }

    func saveContext() {
        if context.hasChanges {
            do {
                try context.save()
                print("Data Saved to Context")
            } catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }

    @discardableResult
    func insertLanguage(language: Setting) -> Bool {
        let entity = NSEntityDescription.entity(forEntityName: "Languages", in: self.context)
        if let entity = entity {
            let managedObject = NSManagedObject(entity: entity, insertInto: self.context)
            managedObject.setValue(language.isChecked, forKey: "isChecked")
            managedObject.setValue(language.title, forKey: "title")
            managedObject.setValue(language.code, forKey: "code")
            managedObject.setValue(language.icon, forKey: "icon")
            
            do {
                try self.context.save()
                return true
            } catch {
                print(error)
                print(error.localizedDescription)
                return false
            }
        } else {
            return false
        }
    }

    @discardableResult
    func deleteAll<T: NSManagedObject>(request: NSFetchRequest<T>) -> Bool {
        let request: NSFetchRequest<NSFetchRequestResult> = T.fetchRequest()
        let delete = NSBatchDeleteRequest(fetchRequest: request)
        
        do {
            try self.context.execute(delete)
            try self.context.save()
            return true
        } catch {
            print(error.localizedDescription)
            return false
        }
    }
}

我可以使用saveContext来保存核心数据,但我也需要更改位置,并且在重新启动后它不起作用。重新启动后,元素的顺序就像我第一次设置的一样。所以我想知道为什么如果我删除所有的数据,它是不起作用的。

如果您能提供任何帮助,我将不胜感激。


共1个答案

匿名用户

批处理删除请求直接转到持久存储区,绕过托管对象上下文。不清楚您何时看到该错误(在删除时保存,还是在插入时保存?)但这可能是因为上下文认为某个对象存在,然后您将其从存储中删除,而不让上下文知道。

因为您只处理少量对象,所以最好不要执行批处理插入(因为您无论如何都需要用结果更新上下文,为什么不单独删除它们然后保存)。

更好的方法是执行upsert(update/insert),它将保持每个语言对象不变,只更新属性。这将维护对象之间的任何关系,并防止在代码的其他部分持有对语言对象的引用时出现不可访问的错误。

您可以在以下网址阅读关于核心数据中的upserts:https://www.upbeat.it/upsert-in-core-data/