CDShare
示例
要运行示例项目,请先克隆仓库,然后从Example目录运行pod install
需求
iOS 11.0+
Xcode 10
安装
CDShare可通过CocoaPods获取。安装它,只需简单地将以下行添加到您的Podfile中
pod 'CDShare'
用法
本作品受到Apple iWork办公套件应用在iOS上工作方式的启发,特别是启发如何实现在离线模式下应用程序间文档共享的特定功能。
CDShare
将回答问题
如何在 2*n
个应用程序之间共享 CoreData,其中 n >= 1?
在进入主题之前,我们先简要介绍一下本教程中涉及到的各个部分。
什么是 CoreData?
CoreData 是由 Apple 创建的框架,用于对象层建模管理。它提供了一般解决方案来处理与对象生命周期、对象管理和持久化相关的功能。在这个框架中应当提到的以下类
NSPersitentStoreCoordinator / NSPersitentStoreContainer
NSManagedObjectModel
NSManagedObjectContext
NSManagedObject
iOS 应用程序结构
为了在 2*n
个应用程序之间共享 CoreData,我们面临一些障碍。
iOS 中,每个应用程序都是通过临时存储(Sandbox)与其他应用程序完全隔离的。这是 Apple 为了安全目的有意为之的。这些限制涉及到进程间通信以及应用程序之间的目录/文件访问。通常情况下,您无法访问运行进程之外的其他应用程序的目录结构。
带有 iCloud 的应用程序目录结构
无 iCloud 的应用程序目录结构
App 组
如果应用程序在同一 App 组中,您将具备访问和相互通信的权限。
每个应用程序运行在单独的进程中,即使应用程序属于同一个 App 组,它们也不会相互访问目录,但它们可以使用具有沙盒式目录结构的共享容器。
应用程序间的进程结构
首先,您需要为您的应用程序创建 App 组。前往 Apple 开发者会员中心 注册 App 组。填写描述和标识符,并按照说明操作。
然后,在创建应用程序或扩展的标识符时,别忘了启用服务 App 组。
然后前往应用程序或扩展,编辑服务。这真的很简单,请参考下面的截图
这些都是设置,现在打开 Xcode,让我们开始编写代码。在 Xcode 中针对每个目标,在目标设置中启用 App 组。
请对所有应用程序或扩展的 App 组执行此程序。
CDShare 逻辑
在共享容器中创建一个文件夹,在该文件夹中保存 SQLite
文件,并为每个应用程序创建一个子文件夹,子文件夹名称为每个应用程序的捆绑 ID。在这些文件夹中,我们将保存具有唯一名称的文件,其中包含通过名为 .CoreDataSaveNotification
的通知接收到的有效负载。
FolderWatcher
是 CDShare.framework
中的关键组件之一。对于每个应用程序,我们都会有一个 FolderWatcher
,我们从每块应用程序接收事件,每当其中一个应用程序在该文件夹中写入任何内容时,我们都会收到这些事件。对于每个事件,我们将处理在该文件夹中写入的所有文件。对于每个应用程序,我们将处理 CoreData 通知 .CoreDataSaveNotification
,如果通知包含我们对 .sharedInScopeEntityNames
感兴趣的模型的任何更改,那么该通知将以具有唯一名称的文件保存到写入文件夹中。写入事件将在每个应用程序中触发读取事件。在读取并合并应用程序中的新更改后,文件将被删除。
iOS 应用状态
在 iOS 中,应用有 5 种状态,这些状态在下面的示意图中展示
FolderWatcher
在应用进入后台时将一直工作,fileDescriptor EventHandler
会被放入队列中,当应用再次进入活动状态时,队列中的事件将被触发。对于 fileDescriptor
的操作会自动发生,你不需要额外的处理程序。
示例说明
在示例文件夹下,你可以找到一个关于如何使用 CDShare.framework
的项目。该项目将展示应用和它的扩展,它们将共享 CoreData。
此示例将基于你可以在以下链接中找到的另一个教程:这里。
框架的逻辑如下
- 创建一个实现
ApplicationGroupInfo
协议的类/结构体。
struct ApplicationGroupInfoModel: ApplicationGroupInfo {
var group: ApplicationIdentifier = ApplicationIdentifierModel(identifier: "group.voda.the.cdshare")
var reading: ApplicationIdentifier = ApplicationIdentifierModel(identifier: "com.CDShareExample")
var writing: [ApplicationIdentifier] = [ApplicationIdentifierModel(identifier: "com.CDShareExample.CDShareExampleToday")]
}
你可以为读取和写入提供不同的上下文,为了示例方便,我使用了相同的上下文。
ApplicationGroupInfo
协议的每个参数都需要是 ApplicationIdentifier
协议的后代。
struct ApplicationIdentifierModel: ApplicationIdentifier {
var identifier: String
}
- 创建
CoreDataShareConfiguration
实例。
let context: NSManagedObjectContext = ...
let configuration = try! CoreDataShareConfiguration(ApplicationGroupInfoModel(), readingContext: context, writingContext: context)
- 创建
CoreDataShare
实例。
let coreDataShare = try! CoreDataShare(configuration: configuration, viewContext: context)
- 不要忘记添加你想要更新/重载内存中对象的类类型。
coreDataShare.sharedInScopeEntityNames = [String(describing: Counter.self)]
- 添加
.CoreDataShareDidSave:
的通知。
let selector = #selector(reloadObjects)
NotificationCenter.default.addObserver(self, selector: selector, name: .CoreDataShareDidSave, object: nil)
作者
vodaion, [email protected]
许可证
CDShare 在 MIT 许可证下可用。有关更多信息,请参阅 LICENSE 文件。应用文档。