是否有必要对 CoreData 使用合并策略并允许外部存储以避免崩溃?

Is it necessary to use merge policy with CoreData and Allows external storage to avoid crash?

我使用 CoreData + NSPersistentCloudKitContainer 来备份我的模型。我的一个 NSManagedObject 有一张存储为二进制数据的图片,并选中了允许外部存储。

这是非常随机的,但有时当我调用 context.save() 时,即使我没有编辑此对象,我也会遇到合并冲突。事实上,我只是尝试创建一个新对象(与有冲突的对象类型不同),但崩溃发生在另一个对象上。

External Data Reference:

的自引用外,其他值都是相同的
    ERROR AppDelegate.saveContext():262 - Unresolved error Error Domain=NSCocoaErrorDomain Code=133020 "Impossible de fusionner les changements." UserInfo={conflictList=(
    "NSMergeConflict (0x600002c62f40) for NSManagedObject (0x60000158da40) with objectID '0x816659a4c358c32f <x-coredata://CEAE3B14-5782-4C18-AAE8-B05D91CFEC8A/Aquarium/p5>' with oldVersion = 56 and newVersion = 57 and old object snapshot = {\n    albums = \"<null>\";\n    aquaID = 6;\n    dateDeCreation = \"2022-01-15 18:24:00 +0000\";\n    imageData = External Data Reference: <self = 0x60000158db80 ; path = 1B9355A6-4101-479D-81F1-DFC106BBCD75 ; length = 1617016>;\n    nom = 11321;\n    volume = 60;\n} and new cached row = {\n    albums = \"<null>\";\n    aquaID = 6;\n    dateDeCreation = \"2022-01-15 18:24:00 +0000\";\n    imageData = External Data Reference: <self = 0x6000015ccf50 ; path = 1B9355A6-4101-479D-81F1-DFC106BBCD75 ; length = 1617016>;\n    nom = 11321;\n    volume = 60;\n}"
), NSExceptionOmitCallstacks=true}, ["NSExceptionOmitCallstacks": 1, "conflictList": <__NSArrayM 0x600003a25ec0>(
NSMergeConflict (0x600002c62f40) for NSManagedObject (0x60000158da40) with objectID '0x816659a4c358c32f <x-coredata://CEAE3B14-5782-4C18-AAE8-B05D91CFEC8A/Aquarium/p5>' with oldVersion = 56 and newVersion = 57 and old object snapshot = {
    albums = "<null>";
    aquaID = 6;
    dateDeCreation = "2022-01-15 18:24:00 +0000";
    imageData = External Data Reference: <self = 0x60000158db80 ; path = 1B9355A6-4101-479D-81F1-DFC106BBCD75 ; length = 1617016>;
    nom = 11321;
    volume = 60;
} and new cached row = {
    albums = "<null>";
    aquaID = 6;
    dateDeCreation = "2022-01-15 18:24:00 +0000";
    imageData = External Data Reference: <self = 0x6000015ccf50 ; path = 1B9355A6-4101-479D-81F1-DFC106BBCD75 ; length = 1617016>;
    nom = 11321;
    volume = 60;
}

我怀疑在加载应用程序和我第一次调用备份之间数据引用发生了变化。 但是长度是一样的,因为这个值在用户端没有改变,所以我不明白为什么引用会改变。

我现在没有使用任何合并策略,它只是不保存。

我可以使用 NSMergeByPropertyObjectTrumpMergePolicy 来确保安全吗?还是我应该找出引用更改的原因?

我从未使用过 CoreData 外部数据引用,所以这是一个大胆的猜测。
在我看来,合并冲突的出现是因为对外部文件的引用发生了变化,尽管文件的路径保持不变。
这可能是自定义合并策略的情况。您必须通过自己的代码解决合并冲突,该代码只需选择其中一个引用,因为两者都指向同一个文件。
我最近尝试为不同的情况设置我自己的自定义合并策略,但我不完全确定我做对了,请查看我的问题、相关代码和参考资料 here。也许您可以针对自己的情况测试类似的代码。

编辑
关于你的问题,如果你可以使用 NSMergeByPropertyObjectTrumpMergePolicy:根据合并冲突,除了 imageData 引用之外,你的实体的所有属性都保持不变。因此,在尝试使用自定义合并策略之前,您应该明确尝试标准合并策略:
NSMergeByPropertyObjectTrumpMergePolicy 仅更新托管上下文中的 imageData 引用,而 NSMergeByPropertyStoreTrumpMergePolicy 仅更新持久存储中的 imageData 引用。但是由于所有其他属性都没有改变,并且两个实体中的文件路径相同,您同样可以尝试使用托管上下文或持久存储中的整个实体的 NSOverwriteMergePolicyNSRollbackMergePolicy,分别见the docs。仅当由于外部引用而失败时,您才应考虑自定义合并策略。