Cirrus 为 CloudKit 提供简单的同步功能,适用于 Codable
Swift 模型。 与其支持所有 CloudKit 功能,Cirrus 更注重简洁性、可靠性和符合 Swift 值类型的工效学设计。
主要特性 | |
---|---|
🙅 | 不再需要处理 CKRecord 、CKOperation 或 CKSubscription |
👀 | 使用 Combine 观察模型和 iCloud 帐户更改 |
📲 | 自动 CloudKit 推送通知订阅 |
🚀 | 简洁的架构,简洁而强大的 API |
🎁 | 自包含,没有外部依赖项 |
在 安装 并按照 Apple 的步骤 在您的 App 中启用 CloudKit 后
// AppDelegate.swift
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
...
application.registerForRemoteNotifications()
...
}
CloudKitCodable
import CloudKitCodable
struct Landmark: CloudKitCodable {
struct Coordinate: Codable {
let latitude: Double
let longitude: Double
}
let identifier: UUID
let name: String
let coordinate: Coordinate
// MARK: - CloudKitCodable
/// A key that uniquely identifies the model. Use this identifier to update your
/// associated local models when the sync engine emits changes.
var cloudKitIdentifier: CloudKitIdentifier {
return identifier.uuidString
}
/// Managed by the sync engine, this should be set to nil when creating a new model.
/// Be sure to save this when persisting models locally.
var cloudKitSystemFields: Data? = nil
/// Describes how to handle conflicts between client and server models.
public static func resolveConflict(clientModel: Self, serverModel: Self) -> Self? {
// Use `cloudKitLastModifiedDate` to check when models were last saved to the server
guard let clientDate = clientModel.cloudKitLastModifiedDate,
let serverDate = serverModel.cloudKitLastModifiedDate else {
return clientModel
}
return clientDate > serverDate ? clientModel : serverModel
}
}
SyncEngine
import Cirrus
let syncEngine = SyncEngine<Landmark>()
SyncEngine
以处理远程更改// AppDelegate.swift
func application(
_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]
) {
syncEngine.processRemoteChangeNotification(with: userInfo)
...
}
// Upload new or updated models
syncEngine.upload(newLandmarks)
// Delete models
syncEngine.delete(oldLandmark)
// Observe remote model changes
syncEngine.modelsChanged
.sink { change in
// Update local models
switch change {
case let .updated(models):
...
case let .deleted(modelIDs):
...
}
}
// Observe iCloud account status changes
syncEngine.$accountStatus
.sink { accountStatus in
switch accountStatus {
case .available:
...
case .noAccount:
...
...
}
}
就是这样! Cirrus 也支持同步多种模型类型,只需为您想要同步的每种类型初始化和配置一个新的 SyncEngine
。
要查看 Cirrus 如何集成到应用程序中的示例,请克隆此存储库并打开 CirrusExample Xcode 项目。
您可以通过将其作为包依赖项添加到 Xcode 项目中来添加 Cirrus。
Cirrus 仅支持私有 iCloud 数据库。 如果您需要将数据存储在公共 iCloud 数据库中,那么 Cirrus 不适合您。
CloudKitCodable
模型上的嵌套 Codable
类型不会作为单独的 CKRecord
引用存储; 它们会作为 Data
blobs 保存在顶层 CKRecord
上。 这导致了两个重要的注意事项
CKRecord
有一个 1 MB 数据限制,因此大型模型可能不适合单个记录。 SyncEngine
不会尝试同步任何大于 1 MB 的模型。 如果您遇到此限制,请考虑通过创建具有相互标识符引用的离散 CloudKitCodable
模型来规范化您的数据。 您可以使用多个 SyncEngine
来同步每种模型类型。CKAsset
并存储在 CloudKit 中。 如果您需要存储由子模型上的本地文件 URL 引用的文件,您可以覆盖模型上的 Encodable
encode(to:)
和 Decodable
init(from:)
方法,以将文件 URL 设置为顶级 CloudKitCodable
类型的编码容器上的键。 然后,SyncEngine
将能够将您的文件同步到 iCloud。本库是在 MIT 许可证下发布的。 有关详细信息,请参阅 LICENSE。
感谢 Tim Bueno 帮助构建 Cirrus。