CloudKit — CKModifyRecordsOperation

CKModifyRecordsOperation 是什么? #

CKModifyRecordsOperation 是 Apple 提供的 CloudKit Framework 中的一个操作类,用于批量创建、修改或删除 CloudKit 数据库中的 records。

CloudKit 的核心概念之一是 Record(记录),它类似于传统数据库的一行数据,由 CKRecord 表示。而 CKModifyRecordsOperation 是操作 CKRecord 的一种高级工具,它允许你一次性创建、更新或删除多个记录。


使用场景 #

在以下场景下需要使用 CKModifyRecordsOperation

  1. 批量处理多条记录

    • 如果需要一次性创建、更新或删除多条记录,而不是单独调用 savedelete 方法处理每一条记录。
    • 它适合需要优化性能或合并网络请求的场景。
  2. 复杂自定义操作需求:

    • 如果你需要在操作完成时提供复杂的回调,比如每条记录的独立处理结果。
    • 或者你需要在操作中定义特定的配置,比如每条记录的冲突解决策略
  3. 异步与长时间操作逻辑

    • CKModifyRecordsOperation 是一种异步的批处理方式,尤其适合需要在后台进行长时间的记录操作。

基础用法 #

1. 创建、更新或删除 CloudKit 记录 #

你可以使用 CKModifyRecordsOperation 来同时:

  • 创建新记录;
  • 更新现有记录(通过提供需要更新的 CKRecord);
  • 删除指定记录(通过提供 CKRecord.ID)。

示例代码:创建和更新记录 #

import CloudKit

func modifyRecords() {
    // 获取默认公共数据库
    let database = CKContainer.default().publicCloudDatabase
    
    // 要创建的记录
    let newRecord = CKRecord(recordType: "Task")
    newRecord["title"] = "New Task"
    newRecord["isCompleted"] = false
    
    // 要更新的记录(假设已有记录 ID)
    let recordIDToUpdate = CKRecord.ID(recordName: "existing_record_id")
    let existingRecord = CKRecord(recordType: "Task", recordID: recordIDToUpdate)
    existingRecord["title"] = "Updated Task Title"
    
    // 创建 `CKModifyRecordsOperation`
    let modifyOperation = CKModifyRecordsOperation(recordsToSave: [newRecord, existingRecord], recordIDsToDelete: nil)
    
    // 配置操作的回调
    modifyOperation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in
        if let error = error {
            print("Error modifying records: \(error.localizedDescription)")
        } else {
            if let savedRecords = savedRecords {
                print("Successfully saved records: \(savedRecords)")
            }
            if let deletedRecordIDs = deletedRecordIDs {
                print("Successfully deleted records with IDs: \(deletedRecordIDs)")
            }
        }
    }
    
    // 将操作添加到数据库队列中
    database.add(modifyOperation)
}

输出示例: #

Successfully saved records: [<CKRecord: 0x...; recordID=<Task: 'generatedID1'>, ...>]

2. 删除记录 #

除了创建和更新,你也可以通过提供 CKRecord.ID 删除记录。

示例代码:删除记录 #

func deleteRecords() {
    let database = CKContainer.default().publicCloudDatabase
    
    // 指定要删除的记录 ID
    let recordIDToDelete = CKRecord.ID(recordName: "record_to_delete_id")
    
    // 创建 `CKModifyRecordsOperation`
    let modifyOperation = CKModifyRecordsOperation(recordsToSave: nil, recordIDsToDelete: [recordIDToDelete])
    
    // 配置操作的回调
    modifyOperation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in
        if let error = error {
            print("Error deleting records: \(error.localizedDescription)")
        } else {
            if let deletedRecordIDs = deletedRecordIDs {
                print("Successfully deleted records with IDs: \(deletedRecordIDs)")
            }
        }
    }
    
    // 将操作添加到数据库队列中
    database.add(modifyOperation)
}

输出示例: #

Successfully deleted records with IDs: [<record_to_delete_id>]

高级用法 #

1. 配置每条记录的结果处理 #

除了完成后的总回调,你还可以针对每条记录设置单独的处理逻辑(比如修改、失败的记录)。

示例代码:逐条回调处理 #
let modifyOperation = CKModifyRecordsOperation(recordsToSave: [newRecord, existingRecord], recordIDsToDelete: nil)

// 设置逐条保存记录的回调
modifyOperation.perRecordCompletionBlock = { record, error in
    if let error = error {
        print("Error saving record \(record.recordID): \(error.localizedDescription)")
    } else {
        print("Successfully modified record \(record.recordID)")
    }
}

// 配置完成后的总回调
modifyOperation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in
    if let error = error {
        print("Operation failed: \(error.localizedDescription)")
    } else {
        print("Operation completed.")
    }
}

2. 配置冲突解决策略 #

在 CloudKit 中,同一条记录可能因为用户多端操作而产生冲突。例如,A 和 B 同时修改了记录 record1,这时需要解决冲突。

你可以通过设置 savePolicy 来定义保存策略:

  • .ifServerRecordUnchanged:如果服务器上的记录未更改,则保存本地记录,否则失败。
  • .changedKeys:只保存本地记录中被修改的字段(其余不变)。
  • .allKeys:保存本地记录的所有字段,覆盖服务器上的记录。
示例代码:使用 .changedKeys 策略 #
modifyOperation.savePolicy = .changedKeys

3. 设置操作的质量和优先级 #

CKModifyRecordsOperation 支持为操作设置优先级和质量服务:

modifyOperation.qualityOfService = .userInitiated // 高优先级,用于与用户交互相关的操作

错误处理 #

modifyRecordsCompletionBlockperRecordCompletionBlock 中,CloudKit 可能返回以下常见错误:

  1. CKError.partialFailure

    • 一些记录成功,但其他记录失败。
    • 错误提示在 CKError.userInfoCKPartialErrorsByItemIDKey 中。
  2. CKError.networkUnavailableCKError.networkFailure

    • 网络问题导致请求未完成。
    • 可以实现重试逻辑。
  3. CKError.serverRecordChanged

    • 本地记录与服务器的不一致,通常由于多个设备同时编辑。
    • 解决方案:使用冲突解决策略(如 .changedKeys)或手动合并。

优势与限制 #

优势 #

  • 批量操作:一次性保存、更新、删除多个记录。
  • 逐条结果控制:能在回调中分别处理每个记录的成功或失败。
  • 配置灵活性:支持冲突解决策略、优先级设置、多种质量控制。

限制 #

  • 操作数量受限:单次操作的记录数有上限,通常是 400 条(视记录数据量大小而定)。
  • 网络依赖性:操作需要网络连接,脱机时无法使用,需要实现网络恢复后的重试逻辑。

总结 #

CKModifyRecordsOperation 是 CloudKit 提供的强大工具,适合需要高性能批量处理的场景,比如同时创建/更新/删除多条记录。关键点包括:

  1. 提供 recordsToSaverecordIDsToDelete 指定需要操作的数据。
  2. 配置 savePolicy 冲突解决策略,比如是否覆盖服务器记录。
  3. 管理异步操作结果,通过回调检查每条记录的状态。

通常在复杂场景或性能要求较高时,推荐使用 CKModifyRecordsOperation,而在简单场景中直接使用 CKDatabase 的单条 savedelete 方法可能更便捷。

本文共 1725 字,上次修改于 Jan 19, 2025