使用 CKContainer 查询 CloudKit 同步状态

了解如何通过 CloudKit 的 accountStatus() 方法,查询用户 iCloud 账户的同步状态。

使用 CKContainer 查询 CloudKit 同步状态

理解 CKAccountStatus:表示 iCloud 可用状态

💡
"CK" 是 CloudKit 的缩写。

CKAccountStatus 是 CloudKit 框架中,用于表示用户 iCloud 账户可用性的枚举,提供了 5 种状态:

https://developer.apple.com/documentation/cloudkit/ckaccountstatus

开发文档的解释如下:

理解 CKContainer 类(基础)

CKContainer 是 CloudKit 框架中的核心类,它代表了一个 iCloud 容器。每个容器可以理解为云端数据存储的一个隔离环境。

CKContainer 同级的其他类

CloudKit 框架包含多个类,分别用于不同的职责:

  • CKQuery - CloudKit 查询,用于检索云端数据
  • CKQueryOperation - CloudKit 查询操作
  • CKRecord - CloudKit 记录,代表云中存储的一个数据项

查询 CloudKit 同步状态主要使用 CKContainer 中的方法,因此,这篇文章主要讲解 CKContainer 类。

CKContainer 负责的功能

身份验证与访问控制

  • 确定用户是否登录了 iCloud 账户
  • 管理应用对 iCloud 数据的访问权限
  • 提供用户身份信息(在保护隐私的前提下)

数据库访问

  • 提供对三种数据库的访问:
    • publicCloudDatabase(公共数据库,所有用户可读)
    • privateCloudDatabase(私有数据库,仅用户本人可访问)
    • sharedCloudDatabase(共享数据库,用于协作)

容器配置

  • 管理云端存储配额
  • 提供容器元数据和配置信息

CKContainer.default()

每个启用了 iCloud 能力的应用都至少有一个容器。

当你的代码调用 CKContainer.default() 时,获取的是应用的默认容器。

通过这个容器对象,可以执行所有 CloudKit 相关操作,包括身份验证、数据存储、查询等。

CKContainer.default().accountStatus()

accountStatus 方法用于确定当前设备上的 iCloud 账户状态,返回的 CKAccountStatus 枚举。

这个方法是开发 iCloud 功能的第一步,因为在确认用户有可用的 iCloud 账户前,其他 CloudKit 操作都无法进行。

使用 accountStatus() 方法查询同步状态

accountStatus() 是 CloudKit 框架中的 CKContainer 类中的一个方法。它会返回一个 CKAccountStatus 对象。

https://developer.apple.com/documentation/cloudkit/ckcontainer/accountstatus(completionhandler:)

Apple 为 accountStatus() 方法提供了新的 Swift Concurrency 版本:

我们可以创建一个 fetchCloudKitAccountStatus() 方法,用于获取同步状态,并添加 logger 输出:

自定义的 fetchCloudKitAccountStatus() 方法

在 View 中显示状态

使用 MVVM 架构,

  • 创建一个 CloudSyncViewModel 文件,用于获取 iCloud 同步状态
  • 创建一个 CloudSyncSettingsView 文件,用于展示 iCloud 同步状态

由于 CloudKit 框架中的 CKAccountStatus 枚举并没有内置本地化的 description 描述,因此,我们还需要创建一个 iCloudStatus 枚举,便于显示本地化文本信息:

import SwiftUI

/// iCloud 状态枚举
enum iCloudStatus {
    case checking
    case enabled  // 我们自定义的"已启用"状态
    case available  // 对应CKAccountStatus.available - 用户的iCloud账户可用
    case noAccount  // 对应CKAccountStatus.noAccount - 设备没有登录iCloud账户
    case restricted  // 对应CKAccountStatus.restricted - 系统拒绝访问用户的iCloud账户
    case temporarilyUnavailable  // 对应CKAccountStatus.temporarilyUnavailable - 用户的iCloud账户暂时不可用
    case couldNotDetermine  // 对应CKAccountStatus.couldNotDetermine - CloudKit无法确定用户的iCloud账户状态

    var description: String {
        switch self {
        case .checking:
            return "检查中..."
        case .enabled:
            return "已启用"
        case .available:
            return "账户可用"
        case .noAccount:
            return "未登录iCloud"
        case .restricted:
            return "访问受限"
        case .temporarilyUnavailable:
            return "暂时不可用"
        case .couldNotDetermine:
            return "状态未知"
        }
    }

    var message: String {
        switch self {
        case .checking:
            return "正在检查 iCloud 同步状态..."
        case .enabled:
            return "数据正在通过 iCloud 同步至所有使用相同 Apple ID 的设备。"
        case .available:
            return
                "您的 iCloud 账户可用。启用 iCloud 同步后,您的用户数据将在所有使用相同 Apple ID 的设备上保持同步。"
        case .noAccount:
            return "设备未登录 iCloud 账户。请在系统设置中登录 iCloud 账户以启用同步功能。"
        case .restricted:
            return "系统拒绝访问您的 iCloud 账户。请检查您的隐私设置。"
        case .temporarilyUnavailable:
            return "您的 iCloud 账户暂时不可用,请稍后再试。"
        case .couldNotDetermine:
            return "CloudKit 无法确定您的 iCloud 账户状态,请检查网络连接后再试。"
        }
    }

    var color: Color {
        switch self {
        case .checking:
            return .gray
        case .enabled:
            return .green
        case .available:
            return .blue
        case .noAccount, .restricted, .temporarilyUnavailable,
            .couldNotDetermine:
            return .orange
        }
    }
}