iCloud + CoreData – 如何避免预填充的数据重复?

我有一个iCloud鞋盒应用程序的问题,希望有人可以帮助我(我已经花了很多小时的战斗)。

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

除了iCloud之外,一切工作都非常完美 – 除非第一次打开应用程序(当时他也可以脱机),否则用户可以开始使用一些预先填充的空白类别。 这是魔鬼。

这是我做的 – 一旦我的persistentStoreCoordinator设置我发送通知

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

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

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

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

任何想法如何可以解决?

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

 [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:

  • 我所有的类别都有创build时间戳。
  • 从iCloud插入,获取具有相同名称的类别对(如果有的话)
  • select较旧的重复类别
  • 将他们的项目移动到较新的重复类别
  • 删除较旧的重复类别

这些策略有效地删除两个设备上的重复,甚至在它们出现在用户界面之前

1)来自第一个设备的项目在第二个设备上迷路了 – 当他们来到第二个设备时,他们的父类别不存在,并且他们的类别字段等于零,所以我不知道把它们放在哪里。

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

3)来自第二设备的一些项目也由于冲突而丢失。

我试图偏好较旧的类别,但没有任何效果

策略2:

  • 我所有的类别都有创build时间戳。
  • 所有类别在创build时都将布尔型字段设置为NO
  • 从iCloud插入,获取具有相同名称的类别对(如果有的话)
  • select较旧的重复类别
  • 将他们的项目移动到较新的重复类别
  • 旧的= YES标记旧的类别

这些策略几乎总是删除两个设备上的重复,甚至在它们出现在用户界面之前

来自两个设备的大部分(或全部)物品由于类别和项目上的一系列冲突而丢失。

一些结论性的想法:

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

在我的testing中,我有两个设备同时运行。 我不能忽视一个情况,当一个刚买了他的第二个iDevice的快乐用户在第二个设备上安装我的应用程序(用tre第一个设备运行应用程序),并在几分钟内丢失了所有的项目。

任何想法如何可以解决这种情况? 你认为iCloud + CoreData已经准备好了吗?

策略3

我试图把一个预先填充的数据库(从捆绑复制)到适当的path。 它部分解决了 – 我没有更多预先填充的类别重复, 添加到预填充类别的项目不会在设备之间同步。

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

在iCloud安装后插入存储的额外类别(以及类别本身)中的项目可以正确同步。

策略1有一些修改似乎是一个工作的解决scheme(虽然有一些缺陷)。

传说:

  • 第一台设备 – 在没有任何内容的情况下在线启动
  • 第二台设备 – 比第一台晚,并离线。 然后它添加一些项目后上线

所以这里是更新的策略:

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

  • 类别不能重命名(只添加或删除 – 这是至关重要的)

  • 我所有的项目都有一个stringcategoryName字段,它在创build项目时获得它的值,并且当项目被移动到不同的类别时被更新 – 这些冗余信息有助于获得成功;

在插入新类别时

  • 从iCloud插入,我得到的类别对有相同的名称,如果有的话

  • select较新的重复类别(他们最有可能比旧的更less的项目,所以我们将减less在iCloud舞蹈)

  • 将其项目移至较旧的重复类别

  • 删除较新的重复类别

插入新物品时 – 如果物品属于已删除类别:

  • CoreData试图合并它并失败,因为没有父类别(控制台中有很多错误)。 它有希望稍后插入它。

  • 经过一段时间后,它会合并 ,并将项目插入存储,但与NIL类别

  • 在这里,我们select我们的项目,找出它从categoryName的父类别,并把它放到正确的类别

瞧! – 没有重复和每个人都高兴

几个注意事项:

  1. 在两台设备上,我都会看到属于第二台设备(与第一台设备无关的设备)的舞蹈。 几分钟后,一切都稳定了
  2. 没有物品丢失了
  3. 跳舞只发生在第二个(或任何其他后续设备)的第一个iCloud同步上,
  4. 如果第二个设备是第一次在线启动,出现重复类别案例的机会只有大约25% – 在3G连接上testing – 所以跳舞不应该影响大多数用户