本文介绍了iCloud + CoreData - 如何避免预填充数据重复?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 iCloud 鞋盒应用程序时遇到问题,希望有人能帮助我(我已经花了很多时间来解决它,但徒劳无功).

I have a problem with an iCloud shoebox application and hope some-one can help me (I've spent many hours fighting it in vain).

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

The App: - A simple library style application - containing set of categories (Cat1 .. CatN) each containing items (Item1...ItemM). I used Apple's iPhoneCoreDataRecipes to set up iCloud CoreData stack.

除了 - 用户第一次打开应用程序后,应该有许多预填充的空类别可以开始使用(当时他也可以处于离线状态),一切都在 iCloud 上运行得几乎完美.这就是魔鬼.

Everything works almost perfect with iCloud except - there should be a number of pre-filled empty categories the user can start using once he has opened the app for the first time (he can also be offline at that time). And here's the devil.

这就是我要做的 - 一旦我的 persistentStoreCoordinator 设置好,我就会发送通知

Here's what I do - Once my persistentStoreCoordinator is setup I send notification

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

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

which is received by my MasterViewController. When the notification is received MasterViewController checks the number of categories in the storage. If the number of available categories equals 0 - the pre-filled categories are inserted.

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

FYI - I use NSMergeByPropertyObjectTrumpMergePolicy for my ManagedObjectContext

问题:这适用于第一台设备.但是对于第二台设备,来自 iCloud 的默认类别经常在设置 PersistentStoreCoordinator 之后收到(以及第二台设备插入的默认类别).最后,我在两台设备上都有 2 组名称相同的类别.

The problem: This works well for the 1st device. But for the 2nd device the default categories from iCloud are often received later than persistentStoreCoordinator has been setup (and default categories inserted by 2nd device). In the end I have 2 sets of categories with the same names on both devices.

知道如何解决这个问题吗?

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

Tried solutions: I tried 2 strategies to solve this. Both start in the same way. After I call

[moc mergeChangesFromContextDidSaveNotification: note];

我打电话

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

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

many thanks to Jose Ines Cantu Arrambide from https://devforums.apple.com/thread/126670?start=400&tstart=0 for his reference code - In essence

materializeKeysWithUserInfo:forContext:

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

get managedObjectIds from note.userInfo and retrieves corresponding objects from ManagedObjectContext putting them into a dictionary.

策略 1:

  • 我的所有类别都有创建时间戳.
  • 从 iCloud 插入时,获取同名类别对(如果有)
  • 选择较旧的重复类别
  • 将他们的项目移到更新的重复类别
  • 删除旧的重复类别

这些策略甚至在 UI 中出现之前就有效地删除了两个设备上的重复项但是

These strategy effectively removes duplicates on both devices even before they appear in the UI BUT

1) 来自第一个设备的项目在第二个设备上丢失了 - 当他们到达第二个设备时,他们的父类别不存在并且他们的类别字段等于 nil,所以我不知道把它们放在哪里.

1) the items from 1st device are getting lost on the 2nd device - when they come to the 2nd device their parent category is absent and their category field equal nil so I don't know where to put them.

2) 在很短的时间内,由于冲突,在第二台设备上丢失的项目也在第一台设备上丢失了.

2) in some short time the items that got lost on the 2nd device are also getting lost on the first due to conflicts.

3) 来自第二个设备的一些项目也因冲突而丢失.

3) some items originating from the 2nd device are also lost due to conflicts.

我试图选择较旧的类别而不是较新的类别,但没有任何效果

I tried to prefer older categories against newer but it didn't give any effect

策略 2:

  • 我的所有类别都有创建时间戳.
  • 所有类别在创建时都过时布尔字段设置为NO
  • 从 iCloud 插入时,获取同名类别对(如果有)
  • 选择较旧的重复类别
  • 将他们的项目移到更新的重复类别
  • 过时= YES
  • 标记较旧的类别
  • All my categories have creation time-stamps.
  • All categories have obsolete boolean field set to NO on creation
  • On insert from iCloud, get pairs of categories with same name if any
  • Select older duplicate categories
  • move their items to newer duplicate categories
  • mark older categories with obsolete = YES

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

These strategy almost always removes duplicates on both devices even before they appear in the UI BUT

由于类别和项目上的一系列冲突,来自两种设备的大部分(或全部)项目都丢失了.

the majority (or all) of the items from both devices are getting lost due to a bunch of conflicts on categories and items.

一些总结性想法:

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

It looks like these strategy doesn't work as we start simultaneously changing content ob both devices whereas iCloud is not suitable for such pattern.

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

In my tests I had both devices running simultaneously. I cannot neglect a case when a happy user who has just bought his 2nd iDevice installs my app on the 2nd device (with tre 1st device running the app) and get lost all his items in the matter of minutes.

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

策略 3

我尝试将预填充的数据库(从包中复制)放到适当的路径中.部分解决了 - 我没有更多的预填充类别重复但是添加到预填充类别的项目不会在设备之间同步.

I've tried to put a pre-filled database (copying it from bundle) to the appropriate path. It worked out partly - I have no more pre-filled categories duplication BUT the items added to the pre-filled categories do not synchronize across the devices.

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

iCloud is not aware of the data that exists in the database prior to iCloud setup - my 2nd device receives items, inserted on the 1st device in pre-filled categories, with category = nil.

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

Items in additionally categories (as well as categories themselves) inserted into the storage after iCloud setup do synchronize properly.

推荐答案

经过一些修改的策略 1 似乎是一个可行的解决方案(尽管存在一些缺陷).

Strategy 1 with some modifications appeared to be a working solutions (with some flaws though).

图例:

  • 第一台设备 - 在 iCloud 中没有任何内容的情况下在线启动
  • 第二个设备 - 启动时间晚于第一个且离线.然后在添加了一些项目后它就会上线

这里是更新后的策略:

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

类别不能重命名(只能添加或删除 - 这很重要)

The categories cannot be renamed (only added or deleted - this is crucial)

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

All my items have a string categoryName field which gets its value upon item creation and updated whenever item is moved to a different category - this redundant information helps to achieve success;

关于插入新的类别:

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

  • On insert from iCloud, I get pairs of categories with same name if any

选择较新重复的类别(它们的项目很可能比旧类别少,因此我们在 iCloud 中的舞蹈会减少)

Select newer duplicate categories (they will most probably have less items than old ones so we will have less dance in iCloud)

将他们的项目(如果有)移动到重复类别

Move their items if any to older duplicate categories

删除较新重复的类别

插入新的项目 - 如果项目属于已删除类别:

On insertion of new Items - if the item belongs to deleted category:

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

  • CoreData tries to merge it and fails as there's no parent category any more (lots of errors in console). It promisses to insert it later.

一段时间后,它合并并将项目插入存储,但具有NIL类别

After some short time it does merge and insert the item into storage but with NIL category

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

Here we pick our item up, find out it's parent category from categoryName and put it to the correct category

瞧!- 没有重复和大家开心

VOILA! - no duplicates & everybody happy

一些注意事项:

  1. 我在两台设备上都看到了属于第二台设备的项目(第一台设备的类别为零的项目).几分钟后一切都稳定了
  2. 虽然没有丢失任何物品
  3. 舞蹈仅在第二个(或任何其他后续设备)的第一个 iCloud 同步上发生
  4. 如果第二台设备第一次启动在线,出现重复类别情况的几率只有大约 25% - 在 3G 连接上测试 - 所以跳舞应该不会影响大多数用户莉>
  1. I get a dance of items belonging to the 2nd device (those that will come with nil category to the 1st device) on both devices. After a couple of minutes everything is stabilized
  2. No items is lost though
  3. The dance happens only on the first iCloud sync of the 2nd (or any other subsequent device)
  4. If the 2nd device is started online for the first time the chance that duplicate categories case appears is about 25% only - tested on 3G connection - so dance should not affect the majority of users

这篇关于iCloud + CoreData - 如何避免预填充数据重复?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-16 18:08
查看更多