是否有必要对 CoreData 使用合并策略并允许外部存储以避免崩溃?
我使用 CoreData + NSPersistentCloudKitContainer 来备份我的模型。我的一个 NSManagedObject 有一张存储为二进制数据的图片,并允许检查外部存储。
这是非常随机的,但有时当我调用 context.save() 时,即使我没有编辑此对象,我也会遇到合并冲突。事实上,我只是尝试创建一个新对象(与有冲突的对象类型不同),而崩溃发生在另一个对象上。
除了外部数据引用
的自引用之外,所有值都是相同的:
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 来确保安全吗?还是应该找出引用更改的原因?
I use CoreData + NSPersistentCloudKitContainer to backup my model. One of my NSManagedObject has a picture stored as Binary Data and Allows external storage checked.
It's very random but sometimes when i call context.save()
i get a merge conflict even if i don't have edit this object. In fact i just try to create a new object (different type as the one with conflicts) and the crash is on another object.
Everyting is the same value except the self reference of 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;
}
I suspect the data reference changed between the time the application loads and the first time I call the backup.
But the length is the same since this value has not been changed on the user side, so I don't understand why the reference changes.
I use no merge policy right now and it just don't save.
Can i use NSMergeByPropertyObjectTrumpMergePolicy to be safe or should i find why the reference changed ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我从未使用过 CoreData 外部数据引用,所以这是一个疯狂的猜测。
在我看来,合并冲突的出现是因为对外部文件的引用发生了变化,尽管文件的路径保持不变。
这可能是自定义合并策略的情况。您必须通过自己的代码解决合并冲突,该代码只需选择其中一个引用,因为两者都指向同一个文件。
我最近尝试针对不同的情况设置自己的自定义合并策略,但我不完全确定我做得对,请参阅我的问题、相关代码和参考文献 这里。也许您可以针对自己的情况测试类似的代码。
编辑
关于您的问题,如果您可以使用
NSMergeByPropertyObjectTrumpMergePolicy
:根据合并冲突,除了imageData
引用之外,实体的所有属性都保持不变。因此,在尝试使用自定义合并策略之前,您应该明确尝试标准合并策略:NSMergeByPropertyObjectTrumpMergePolicy
仅更新托管上下文中的imageData
引用,而NSMergeByPropertyStoreTrumpMergePolicy
仅更新来自持久存储的imageData
引用。但由于所有其他属性都没有更改,并且两个实体中的文件路径相同,因此您同样可以尝试使用托管中的整个实体的NSOverwriteMergePolicy
和NSRollbackMergePolicy
上下文或持久存储,分别参见 文档。仅当由于外部引用而失败时,您才应该考虑自定义合并策略。I have never worked with CoreData external data references, so this is a wild guess.
It seems to me that the merge conflict arises because the reference to the external file changed, although the path to the file stayed the same.
This is probably a case for a custom merge policy. You had to resolve the merge conflict by your own code that simply selects one of the references because both point anyway to the same file.
I tried recently to set up my own custom merge policy for a different situation, but I am not completely sure that I did it right, please see my question, related code and references here. Maybe you can test a similar code for your own case.
EDIT
Regarding your question, if you can use
NSMergeByPropertyObjectTrumpMergePolicy
: According to the merge conflict, all properties of your entity stayed the same except theimageData
reference. So, before you try to use a custom merge policy, you should definitively try the standard merge policies:NSMergeByPropertyObjectTrumpMergePolicy
updates only theimageData
reference from the managed context, whileNSMergeByPropertyStoreTrumpMergePolicy
updates only theimageData
reference from the persistent store. But since all other properties did not change, and the file path in both entities is the same, you could equally well tryNSOverwriteMergePolicy
andNSRollbackMergePolicy
that use the entire entity in the managed context or the persistent store, respectively, see the docs. Only if that fails because of the external reference, you should consider a custom merge policy.