0

我有一个核心数据堆栈,它只显式使用主上下文,并且只在 context.performAndWait 块中更改/创建持久对象。如果我需要背景上下文,我总是使用以下代码块:

persistentContainer.performBackgroundTask()
{context in
    context.performAndWait
    {
        defer
        {
            context.save()
            persistentContainer.context.save()
        }
        //make changes here
    }
} 

主上下文的合并策略在创建 persistentStore 时设置为 NSOverwriteMergePolicy,当我保存后台上下文时,我希望用后台上下文中创建的任何“新”对象覆盖主上下文中的任何“旧”对象. 相反,我得到了一个 NSConstraintConflict 错误,因为后台上下文使用默认的合并策略(不知道为什么,我希望它继承主上下文的合并策略。)当我明确设置后台上下文的合并策略时,我最终得到了根据我设置的约束不应该重复的对象的重复。在这种情况下,clientID 属性对于任何给定的 Client 实体都必须是唯一的。

我觉得我在某种程度上没有正确地合并上下文。我现在这样做的方式只是保存背景上下文,然后保存主上下文,或多或少如上所示。但是,如果我没有正确合并,当在背景上下文中创建的对象与主上下文中的对象具有相同的属性时,为什么会发生约束错误?当我在主上下文上执行获取请求时,为什么会出现重复项?

我只有大约两个月的时间使用核心数据,我所知道的一切都来自文档或这里,所以我确信有些东西我只是不知道。关于我做错了什么的任何想法?

4

1 回答 1

2

原来我没有为我看到重复的实体设置约束。设置约束消除了重复的对象。

为了解决每当我保存在后台上下文中时出现 NSConstraintConflict 错误的问题,我使用以下自定义类使使用我正在使用的函数创建的所有后台上下文都具有相同的合并策略:

class MergePolicedNSPersistentContainer: NSPersistentContainer
{
    override func performBackgroundTask(_ block: @escaping (NSManagedObjectContext) -> Void)
    {
        super.performBackgroundTask()
        { context in
            context.mergePolicy = PersistenceManager.shared.mergePolicy
            //PersistenceManager is a custom singleton class where I do lots of custom coreData stuff, mostly sanity checks and locks. In this case I use it to store a merge policy instance to use here.
            block(context)
        }
    }
}

在自定义 PersistenceManager 类中初始化我的数据存储时:

lazy var persistentContainer: MergePolicedNSPersistentContainer = {

    let container = MergePolicedNSPersistentContainer(name: "MyAppDataModel")
    container.loadPersistentStores()
    { (storeDescription, error) in

        container.viewContext.mergePolicy = self.mergePolicy

        if let error = error as NSError?
        {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    }
    return container
}()
于 2019-05-14T04:25:26.337 回答