OGeek|极客世界-中国程序员成长平台

标题: ios - 使用Core Data和Ensembles(iCloud)删除几乎重复的副本 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-12 10:15
标题: ios - 使用Core Data和Ensembles(iCloud)删除几乎重复的副本

摘要

我的问题是我想摆脱基于Coret的iOS项目中使用Ensembles与iCloud同步的几乎重复项。

  • 与iCloud的同步在我的应用程序中基本运行良好。
  • 问题是,当用户在持久存储被Ensembles(连接到iCloud)之前,在多个设备上创建相似的对象时。
  • 这会生成几乎是正确的重复项。
  • 我删除这些重复项的方法似乎不起作用。

  • 详细问题

    用户可以在连接到iCloud之前在不同的设备上创建NSManagedObjects。可以说他有一个名为NSManagedObjectCar,它与一个名为NSManagedObjectPerson有一个“To One”关系,而后者又与Car有一个“To Many”关系。看起来像这样:
    A simplified model

    好的,假设用户有两个设备,并且他在每个设备上创建了两个NSManagedObjects。名为“Audi”的Car和名为“Raphael”的Person。两者通过某种关系联系在一起。在另一台设备上,他创建了一个名为“BMW”的Car和另一个名为“Raphael”的Person。也互相连接。现在,用户在每个设备上都有两个相似的对象:两个名为“Raphael”的Person对象。

    我的问题是,用户在同步后最终将在每个设备上拥有两个名为“Raphael”的Person对象。

    实际上这是正确的,因为当用户释放其持久性存储时,对象将获得其uniqueIdentifiers(以标识Ensembles中的对象)。这些对象实际上是不同的。但这是我要解决的问题。

    我的方法

    我实现了此委托方法,并删除了reparationContext中的重复项。
    - (BOOL)persistentStoreEnsembleCDEPersistentStoreEnsemble *)ensemble 
        shouldSaveMergedChangesInManagedObjectContextNSManagedObjectContext*)savingContext
        reparationManagedObjectContext(NSManagedObjectContext *)reparationContext {
    
        [reparationContext performBlockAndWait:^{
    
            // Find duplicates
            // Change relationships and only use the inserted Person object (the one from iCloud)
            // Delete local Person object
            [reparationContext save:nil];
        }
        return YES;
    }
    

    基本上,这似乎在合并来自第一个设备的数据的第二个设备上很好用。但是不幸的是,即使在reparationContext中删除了本地人,它似乎仍然同步到iCloud。

    由于第一设备随后还合并了来自第二设备的更改并再次替换了已在第二设备上删除的人员,因此这导致了损坏状态。某些同步之后,该人最终在汽车关系中失踪了,该应用引发了同步错误。

    重现问题的步骤
  • 步骤1 (设备1)
  • 创建对象
  • 数据:汽车“Audi”->人员“Raphael(设备1)”
  • 步骤2 (设备2)
  • 创建对象
  • 数据:汽车“宝马”->人“Raphael(设备2)”
  • 步骤3 (设备1)
  • 来自商店
  • 的渗水数据
  • 连接到iCloud
  • 将数据发送到iCloud
  • 数据:汽车“Audi”->人员“Raphael(设备1)”
  • 步骤4 (设备2)
  • 来自商店
  • 的渗水数据
  • 连接到iCloud
  • 合并来自iCloud的数据
  • 用设备1中插入的​​人替换设备2中的本地人
  • 从设备2删除本地人
  • 将数据发送到iCloud
  • 数据:
    汽车“Audi”->人员“Raphael(设备1)”
    汽车“宝马”->人“拉斐尔(设备1)”
  • 步骤5 (设备1)
  • 合并来自iCloud的数据
  • 用设备2中插入的人替换设备1中的本地人(这不应该发生)
  • 从设备1删除本地人员(这不应该发生)
  • 将数据发送到iCloud
  • 预期数据:
    汽车“Audi”->人员“Raphael(设备1)”
    汽车“宝马”->人“拉斐尔(设备1)”
  • 实际数据:
    汽车“Audi”->人员“Raphael(设备2)”
    汽车“宝马”->人“拉斐尔(设备2)”

  • 实际上,本地人对象“Raphael(设备2)”已在步骤4中删除,但似乎仍被发送到iCloud,因为在步骤5中,它是savingContext.insertedObjects委托方法中shouldSaveMergedChangesInManagedObjectContext中的插入内容。

    据我了解,Ensembles首先从iCloud提取更改,通过委托方法询问用户是否一切都如预期,然后合并到持久性存储中,并在合并后将增量发送到iCloud。

    难道我做错了什么?还是这是一个Ensembles错误?



    Best Answer-推荐答案


    lars提到了一个问题。您必须小心,始终确定性地做事。按唯一ID排序是实现此目的的一种方法。

    就个人而言,我将通过以下两种其他方式之一来处理:

  • 在合并完成后再次进行重复数据删除(再次确保它是确定性的)
  • 使用精心选择的全局标识符为您控制重复数据删除。

  • 例如,您可以使用唯一的ID Raphael。您唯一需要注意的是,当您在同一台计算机上创建另一个Raphael时,它称为Raphael_1(或其他名称)。

    如果您的唯一ID很可能是唯一的(例如,名字+姓氏不太可能发生冲突),则Ensembles会自动将该人合并到其他设备上。

    关于ios - 使用Core Data和Ensembles(iCloud)删除几乎重复的副本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34979063/






    欢迎光临 OGeek|极客世界-中国程序员成长平台 (http://ogeek.cn/) Powered by Discuz! X3.4