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

Rei*_*ner 5 core-data pruning cloudkit nspersistentcloudkitcontainer

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

由于持久历史跟踪事务会占用磁盘空间,因此请确定清除策略以在不再需要它们时将其删除。在修剪历史记录之前,单个看门人应确保您的应用程序及其客户端已经使用了他们需要的历史记录。

最初这也是在 26:10 开始的WWDC 2017 演讲中提出的。

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

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

上面引用的 Apple 文档建议:

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

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

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

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

Rei*_*ner 5

更新:

\n

在WWDC22 核心数据实验室的这篇文章中,Apple 核心数据框架工程师回答了“我是否需要清除持久历史跟踪数据? ”的问题,如下所示:

\n
\n

不。我们不推荐它。NSPersistentCloudKitContainer 使用持久历史记录令牌\n来跟踪要同步的内容。如果您删除历史记录\n云同步将被重置,并且必须从头开始上传所有内容。它\n会恢复,但\xe2\x80\x99不是一个好的客户体验。通常应该\xe2\x80\x99t\n需要删除历史记录。例如,Apple Photos 应用程序不会修剪其历史记录,因此除非您生成大量历史记录,否则不要这样做。

\n
\n

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

\n

在 CoreData 中,持久存储由一个或多个持久存储协调器处理。\n如果只有一个,则协调器对存储具有完全控制权,并且不需要历史记录跟踪。

\n

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

\n

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

\n

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

\n

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

\n