6

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

因为持久性历史跟踪事务占用磁盘空间,所以确定一个清理策略以在不再需要它们时将其删除。在修剪历史之前,单一的看门人应该确保您的应用程序及其客户端已经消耗了他们需要的历史。

最初在 26:10 开始的WWDC 2017 演讲中也提出了这一建议。

我的问题是:我如何实现这个单一的看门人?

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

上面引用的 Apple 文档建议:

与获取历史记录类似,您可以使用 deleteHistory(before:) 删除比令牌、交易或日期更早的历史记录。例如,您可以删除所有超过 7 天的交易。

但这并不能解决我心中的问题。

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

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

4

1 回答 1

3

到目前为止,我认为我的问题部分是基于一个误解:

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

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

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

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

如果设备上有多个商店用户,情况就不同了,例如附加的应用程序扩展。在这种情况下,必须确保除应用程序之外的其他目标也已在删除历史记录之前处理了事务。这确实可以由一个看门人完成。例如,这篇文章中描述了如何做到这一点。

于 2021-07-28T16:33:43.227 回答