如何在 CoreData+CloudKit 应用程序中修剪历史记录?

How to prune history right in a CoreData+CloudKit app?

我的应用程序使用 CoreData 和 iCloud 作为后端。多个设备可以访问 iCloud 数据库,因此 .public.
本地 CoreData 存储使用 NSPersistentCloudKitContainer.
与 iCloud 同步 我根据 Apple’s suggestions.
使用历史跟踪 在那里,Apple 建议尽可能修剪历史记录。他们说

Because persistent history tracking transactions take up space on disk, determine a clean-up strategy to remove them when they are no longer needed. Before pruning history, a single gatekeeper should ensure that your app and its clients have consumed the history they need.

最初这也是在 WWDC 2017 talk 中从 26:10 开始建议的。

我的问题是:如何实现这个单一网守?

我假设这个想法是单个实例知道应用程序的每个用户最后一次同步他们的设备的时间。如果是这样,则可以删除此日期之前的交易历史。
但是,如果用户同步了本地数据,然后很长时间不再使用该应用程序怎么办?在这种情况下,在该用户再次同步本地数据之前,无法删除历史记录。所以历史数据可以增长到任意大。这在我看来是一个我不知道如何解决的核心问题。

上面引用的 Apple 文档建议:

Similar to fetching history, you can use deleteHistory(before:) to delete history older than a token, a transaction, or a date. For example, you can delete all transactions older than seven days.

但这并没有解决我心中的问题。

除了这个一般问题,我的想法是在 public iCloud 数据库中有一个 iCloud 记录类型,它直接为每个设备(即没有 CoreData)存储本地数据库更新的最后日期。由于所有设备都可以读取这些记录,因此很容易识别上次更新所有本地数据库的时间,并且我可以在此日期之前删除历史记录。

这是处理问题的正确方法吗?

现在我认为我的问题部分是基于误解:

在 CoreData 中,持久存储由一个或多个持久存储协调器处理。 如果只有一个,coordinator对store有完全的控制权,不需要历史追踪

如果有多个协调员,一个协调员可以更改商店,而另一个协调员不知道更改。 因此,商店的持久历史跟踪记录了商店中的所有交易。 然后商店可以通过发送 NSPersistentStoreRemoteChange 通知来通知商店的其他用户。 收到此通知后,可以获取和处理交易历史记录。 处理交易后,处理它的用户不再需要它。

在 CoreData + CloudKit 情况下,持久存储被镜像到 iCloud。
这意味着在最简单的情况下,应用程序有一个持久存储协调器,并且 - 对应用程序不可见 - 一个执行镜像的持久存储协调器。
由于两个协调员都可以独立更改商店,因此需要跟踪历史。

如果应用更改商店,我假设 Apple 的镜像软件收到 NSPersistentStoreRemoteChange 通知,处理交易并将它们转发到 iCloud。通常情况下,即如果有iCloud连接,这只需要几秒钟,所以交易历史只需要很短的时间。
如果 iCloud 更改反映到商店,应用会收到 NSPersistentStoreRemoteChange 通知,并且必须处理交易。
处理完成后,APP和镜像软件都不需要了,可以剪掉。
这意味着如果应用程序设备上的持久存储只有一个用户,则确实可以在处理通知后短时间内完成修剪。
如果设备离线,例如在飞行模式或关闭时,它不会收到 NSPersistentStoreRemoteChange 通知,也不会删除交易历史记录。 因此,在处理后 7 天后修剪持久历史确实是安全的。

如果一台设备上有多个商店用户,情况就不同了,例如额外的应用程序扩展。在这种情况下,必须确保除应用程序之外的其他目标也已在删除历史记录之前处理了交易。这确实可以由一个网守来完成。如何做到这一点是例如this post.

中描述