⛅️ CombineCloudKit

用于响应式CloudKit记录处理的Swift Combine扩展。设计简洁。

Swift Platforms License Release

Lint | Build | Test Coverage

CombineCloudKit将 CloudKit 操作公开为 Combine 发布者 (Publisher)。发布者可以使用Combine的声明式API来处理随时间变化的值。

⚠️已弃用

很遗憾,我无法继续维护此项目。如果您想fork并维护它,请联系我。

请考虑使用CloudKit和SwiftData中的新的异步功能。

📦 将 CombineCloudKit 添加到您的项目

CombineCloudKit 支持 Swift Package ManagerCocoaPodsCarthage。 您可以使用您喜欢的任何一个,但 Swift Package Manager 最有可能在未来得到支持。

Swift Package Manager

使用 Package.swift 通过 XcodeSwift Package Manager 添加对 CombineCloudKit 的依赖。 (可选)指定一个 版本要求

dependencies: [
  .package(url: "https://github.com/chris-araman/CombineCloudKit.git", from: "1.0.0")
]

然后解析依赖

swift package resolve

要更新到与您的版本要求兼容的最新CombineCloudKit版本

swift package update CombineCloudKit

CocoaPods

在您的 Podfile 中添加对 CombineCloudKit 的 依赖。(可选)指定一个 版本要求

pod 'CombineCloudKit', '~>1.0'

然后 安装 依赖

pod install

更新到与您的版本要求兼容的最新CombineCloudKit版本

pod update CombineCloudKit

Carthage

在您的 Cartfile 中添加对 CombineCloudKit 的依赖。(可选)指定一个 版本要求

github "chris-araman/CombineCloudKit" ~> 1.0

由于 Carthage 假设依赖项以共享框架的形式提供,但 Swift Package Manager 只构建库或可执行文件,因此我们必须生成一个 .xcodeproj 供 Carthage 使用。

⚠️generate-xcodeproj 命令已被弃用。此解决方案可能在 Swift Package Manager 的未来版本中停止工作。

carthage bootstrap --no-build
pushd Carthage/Checkouts/CombineCloudKit && swift package generate-xcodeproj && popd
carthage bootstrap --use-xcframeworks

要更新到与您的版本要求兼容的最新CombineCloudKit版本

carthage update CombineCloudKit --use-xcframeworks

🌤 在您的项目中使用 CombineCloudKit

Combine 允许您为一个或多个 订阅者 (Subscriber) 链接值处理 发布者 (Publisher)。 在这里,我们在我们的 CKDatabase 上执行查询,然后异步处理结果。 当从数据库中读取每个 CKRecord 时,它被传递给 map 发布者,该发布者发布记录的名称字段的值。 到目前为止,链中的任何错误都可以在 catch 发布者中处理,catch 发布者将 CKRecordValue 值传递给我们的 sink 订阅者,最终值在此处处理。

import CloudKit
import Combine
import CombineCloudKit

func queryDueItems(database: CKDatabase, due: Date) {
  let cancellable = database
    .performQuery(ofType: "ToDoItem", where: NSPredicate(format: "due >= %@", due))
    .map { record: CKRecord -> CKRecordValue in
      // Map each ToDoItem to its Name
      print("Received record: \(record)")
      return record["Name"]
    }.catch { error: Error in
      // Handle any upstream error
      print("Received error: \(error)")
    }.sink { value: CKRecordValue in
      // Process the Name of each ToDoItems
      print("Received result: \(value)")
    }

  // ...
}

队列和取消

仅创建 Publisher 不会将 CloudKit 操作排队。 仅当 Subscriber 订阅 Publisher 并指示 Demand 时,才会将操作排队。

请注意,来自 sinkCancellable 订阅者将在取消初始化时取消上游发布者。 请注意确保您的订阅者生存的时间足够长以处理值。 如果在 CombineCloudKit 发布者完成发出值之前被取消,则底层 CKOperation 将被取消。 在执行查询并仅处理前几个结果时,这可能是可取的。 但是,未能等待 savedeletemodify 操作完成可能会导致不希望的取消。

请注意,由于 atBackgroundPriority 发布者构建在 CKDatabase 方法之上,这些方法不提供取消方法,因此它们不会响应取消请求。 如果您需要发布者响应合作取消请求,请使用名称中没有 atBackgroundPriority 的发布者。 您仍然可以通过传入 CKOperation.Configuration 来指定 QualityOfService.background

在多个订阅者之间共享发布者

如果两个或多个 Subscriber 订阅相同的 CombineCloudKit Publisher,则该操作将被排队两次。 如果您是 Combine 的新手,这可能会令人惊讶! 将相同的数据库操作排队两次可能效率低下或可能有害。 如果您需要订阅 Publisher 两次,请使用 sharemakeConnectable 运算符。 这将确保该操作仅排队一次。

我考虑过默认情况下使 Publisher 都符合 ConnectablePublisher,但这要求所有调用者显式调用 connect 或使用 autoconnect 运算符,即使他们不打算共享 Publisher

有关此主题的更多信息,请查看

📘 文档

💯% documented 使用 Jazzy。由 GitHub Pages 托管。

❤️ 贡献

欢迎贡献!

📚 进一步阅读

要了解有关 Combine 和 CloudKit 的更多信息,请观看 WWDC 中的这些视频

...或查看 Apple 的文档

如果您正在寻找使用 asyncawaitAsyncSequence 的 CloudKit 的 Swift 并发扩展,请查看 AsyncCloudKit!

📜 许可

CombineCloudKit 由 Chris Araman 创建。 它是在 MIT 许可证 下发布的。