iCloud +核心数据 - 如何避免预填充数据重复?

时间:2012-02-01 14:30:34

标签: ios core-data synchronization icloud

我对iCloud鞋盒应用程序有疑问,希望有人可以帮助我(我花了很多时间徒劳地对抗它)。

应用程序 - 一个简单的库样式应用程序 - 包含一组类别(Cat1 .. CatN),每个类别包含项目(Item1 ... ItemM)。我使用Apple的iPhoneCoreDataRecipes来设置iCloud CoreData堆栈。

一切都与iCloud完美配合除外 - 用户可以在第一次打开应用程序后开始使用一些预先填充的空类别(他当时也可以离线)。这是魔鬼。

以下是我的工作 - 设置了persistentStoreCoordinator后,我发送通知

dispatch_async(dispatch_get_main_queue(), ^{
    [[NSNotificationCenter defaultCenter]
        postNotificationName: @"RefetchAllDatabaseData"
                      object: self
                    userInfo: nil];
    });

由我的MasterViewController接收。收到通知后,MasterViewController会检查存储中的类别数。如果可用类别的数量等于0 - 则插入预填充类别。

仅供参考 - 我为我的ManagedObjectContext使用 NSMergeByPropertyObjectTrumpMergePolicy

问题:这适用于第一台设备。但对于第二个设备,iCloud的默认类别经常比设置的persistentStoreCoordinator更晚收到(以及第二个设备插入的默认类别)。最后,我在两个设备上都有两组具有相同名称的类别。

如何解决这个问题?

尝试过的解决方案:我尝试了两种策略来解决这个问题。两者都以同样的方式开始。我打电话后

[moc mergeChangesFromContextDidSaveNotification: note];

我打电话

[self materializeKeysWithUserInfo: note.userInfo forContext: moc];

非常感谢来自https://devforums.apple.com/thread/126670?start=400&tstart=0的Jose Ines Cantu Arrambide的参考代码 - 本质上

materializeKeysWithUserInfo:forContext:

从note.userInfo获取managedObjectIds,并从ManagedObjectContext中检索相应的对象,将它们放入字典中。

策略1:

  • 我的所有类别都有创建时间戳。
  • 在从iCloud插入时,获取具有相同名称的成对对象(如果有)
  • 选择较旧的重复类别
  • 将商品移至较新的重复类别
  • 删除较旧的重复类别

这些策略有效地消除了两个设备上的重复项,即使它们出现在用户界面但是

之前

1)来自第一台设备的物品在第二台设备上丢失 - 当他们来到第二台设备时,他们的父类别不存在,他们的类别字段等于零,所以我不知道放在哪里。

2)在短时间内,由于冲突,第二台设备上丢失的物品也会在第一台设备上丢失。

3)源于第二台设备的一些物品也因冲突而丢失。

我试图更喜欢较旧的类别而不是更新但是它没有产生任何影响

策略2:

  • 我的所有类别都有创建时间戳。
  • 所有类别在创建时过时布尔字段设置为
  • 在从iCloud插入时,获取具有相同名称的成对对象(如果有)
  • 选择较旧的重复类别
  • 将商品移至较新的重复类别
  • 使用过时= YES
  • 标记旧类别

这些策略几乎总是删除两个设备上的重复项,即使它们出现在用户界面但是

之前 由于类别和项目上存在大量冲突,两台设备中的大部分(或全部)项目都会丢失。

一些结论性的想法:

看起来这些策略不起作用,因为我们开始同时更改两个设备的内容,而iCloud不适合这种模式。

在我的测试中,我让两台设备同时运行。我不能忽视这样一个案例:一个刚刚购买了他的第二个iDevice的快乐用户在第二台设备上安装了我的应用程序(运行应用程序的第一台设备),并在几分钟内丢失了所有物品。

有关这种情况如何解决的任何想法?您认为iCloud + CoreData已准备好投入生产吗?

策略3

我试图将预填充的数据库(从包中复制)到适当的路径。它部分解决了 - 我没有预先填写的类别重复添加到预填充类别的项目不会在设备之间同步。

iCloud在iCloud设置之前不知道数据库中存在的数据 - 我的第二个设备接收到的项目,插入第一个设备的预填充类别中,类别= nil。

在iCloud设置完成后,插入存储的其他类别(以及类别本身)中的项目会正确同步。

1 个答案:

答案 0 :(得分:3)

经过一些修改的策略1似乎是一种有效的解决方案(虽然存在一些缺陷)。

图例:

  • 第一台设备 - 在线启动,iCloud中没有任何内容
  • 第二个设备 - 比第一个设备启动并脱机。然后在添加一些项目后上线

所以这是更新的策略:

  • 我的所有类别都有时间戳

  • 重新命名 类别(仅添加或删除 - 这一点至关重要)

  • 我的所有项目都有一个字符串categoryName字段,该字段在项目创建时获取其值,并在项目移动到其他类别时更新 - 此冗余信息有助于取得成功;

插入新的类别

  • 在iCloud上插入时,我会得到一组具有相同名称的类别

  • 选择较新重复的类别(他们的项目可能比旧的更少,所以我们在iCloud中的舞蹈会少一些)

  • 将其商品(如果有)移至较旧重复类别

  • 删除较新重复类别

在插入新商品时 - 如果商品属于已删除类别:

  • CoreData尝试合并它,失败,因为不再有父类别(控制台中有很多错误)。它承诺稍后插入。

  • 在很短的时间后合并并将该项目插入存储空间,但 NIL 类别

  • 在这里,我们选择我们的项目,从categoryName中找出它的父类别,并将其放入正确的类别

VOILA! - 没有重复&大家都很开心

几点说明:

  1. 我会在两台设备上跳过属于第二台设备的项目(那些将在第一台设备上添加nil类别的项目)。几分钟后,一切都稳定了
  2. 虽然
  3. 没有丢失任何物品
  4. 舞蹈仅在第二个(或任何其他后续设备)的第一个iCloud同步时发生
  5. 如果第二个设备首次启动在线,那么重复类别案例出现的可能性仅为25% - 在3G连接上进行测试 - 因此舞蹈不应影响大多数用户