platforms: iOS|tvOS|watchOS|macOS|visionOS

Ambar

名词:ambar (复数 ambars)
塞尔维亚的各种地下或谷仓式粮仓。

AmbarContainerNSPersistentContainer 的子类,它实现了两个独立的 NSPersistentStoreCoordinator 实例。

如果您不需要此设置,则应使用 Apple 的 NSPersistentContainer

在这两种情况下,请研究 ManagedObjectType——如果您的模型类采用此协议,它们将获得几个有用的数据获取方法。

注意

安装

只需将此存储库的 URL 添加为 Swift Package Manager 依赖项。 使用 9.0.0 或更新的版本。

如何实现

在以下位置创建 AmbarContainer 的实例:

do {
	coreDataStack = try AmbarContainer(storeURL: url)

} catch let err {
	log(level: .severe, "Failed to setup Core Data store:\n\( err )")
}

默认情况下,Ambar 使用 SQLite 存储类型(我个人从未用过其他任何类型)。

您可以提供要使用的特定模型名称(无扩展名)。 如果不这样做,库将通过合并在应用程序包中找到的所有模型来创建一个模型。

您可以提供将创建 .sqlite 文件的特定目录 URL。 如果您使用 AppGroups(与扩展共享存储),这将非常有用。 如果您不提供它,应用程序将在系统提供的 NSPersistentContainer.defaultDirectoryURL() 方法返回的文件夹中创建存储。

主 (视图) MOC

由于 AmbarContainerNSPersistentContainer 的子类,它已经拥有 viewContext。 您应该使用此 MOC 来驱动您的 UI。

此 MOC 使用 .mergeByPropertyStoreTrump 合并策略,设置为优先考虑持久性存储(磁盘上)中对象的状态,而不是内存中的对象。

如果您想进一步强制执行此操作,可以将 isViewContextReadOnly 属性设置为 true,这将将 mergePolicy 切换到 .rollback,从而静默阻止来自 viewContext 的任何存储写入。

有用的 MOC

该库有三个额外的有用方法来创建特定的 MOC。

func importerContext() -> NSManagedObjectContext

此方法返回附加到上述 writerCoordinator 的 MOC,其合并策略优先考虑内存中对象的状态。 这使得它非常适合后台导入,因为创建/更改的任何内容都会覆盖磁盘上的对象。

从后台队列调用此方法,并使用它来处理项目并将它们直接保存到磁盘,而无需接触主线程。 由于这种处理非常短,因此很容易导入几乎任何内容,并保持 UI 线程的流畅。

func temporaryContext() -> NSManagedObjectContext

此方法返回连接到 mainCoordinator 但具有回滚合并策略的 MOC。 这意味着您可以在该 MOC 中做任何您想做的事情,其中的对象永远不会存储到磁盘。

当我需要 MO 的临时副本用于 UI 目的时,我会使用它。 一个穷人的 NSManagedObject 实例的值类型。

func editorContext() -> NSManagedObjectContext

此方法返回创建为 viewContext 的子上下文的 MOC,但这次使用的合并策略将覆盖您在主 MOC 中的任何内容,并进一步覆盖到磁盘。

此方法的教科书式用法是当您需要创建新对象时,例如购物应用程序中的新订单。 由于这些对象是在新的子 MOC 中创建的,因此您可以自由地在其中做任何事情,而不会影响主上下文中的对象。 如果您删除此上下文,一切都会消失,不会造成任何损害。 如果您保存此上下文,所有内容将首先自动传播到主上下文,然后再进一步传播到磁盘。

杀手级功能:自动、智能的保存合并

如果您仔细阅读,您可能已经注意到 importerContext 连接到 writerCoordinator。 这意味着在其中创建并稍后保存到持久性存储的对象将不会到达 viewContext,因此您的 UI 将不会知道它们。

如果您已经在 viewContext 中加载了一些对象并在 UI 中显示,并且这些对象通过后台导入进行更新并保存到磁盘,那么您的 UI 将不会知道这些更改。 您的 NSFetchedResultsControllerDelegate 回调也不会拾取它们。

那么如何获取它们呢?

Ambar 为您自动处理此问题!

AmbarContainer 实例将自身注册为来自任何上下文的 NSManagedObjectContextDidSaveNotification 的观察者。 然后,它会智能地忽略来自除连接到 writerCoordinator 的上下文之外的任何内容的通知。

借助 Core Data 的强大功能,此合并将刷新已加载到 viewContext 中的所有对象,并忽略其余对象。 这为您提供了两全其美的效果:您可以在后台导入数千个对象,如果您只显示其中的 10 个对象,则会更新这 10 个对象,其余对象永远不会阻塞您的 UI 线程。

此外,如果您巧妙地划分后台导入调用,您可以自由地持续导入数据,而不会遇到合并冲突或遇到内存问题。

回报

如果您发现此代码有用,请考虑 请我喝一两杯咖啡。 ☕️😋