如何取消正在进行中的CloudKit保存/上传操作
如何取消正在进行的CloudKit保存/上传操作
可以主动取消正在进行的CloudKit上传/保存任务,针对你代码里用到的两种不同API,处理方式有区别:
1. 针对database.save(_:completionHandler:)便捷API
- 这个系统封装的便捷方法没有对外暴露可取消的操作对象,一旦调用发起就无法主动终止。
- 如果你的业务场景需要支持中途取消上传(比如用户关闭页面、主动终止上传),不要使用这个API,替换为
CKModifyRecordsOperation实现保存逻辑即可。
2. 针对CKModifyRecordsOperation实现的上传
- 这个操作类继承自
Operation,原生自带cancel()方法,可以随时终止正在执行的上传任务,完全满足你关闭VC时终止上传的需求。
正确实现示例
首先修正你的保存逻辑,去掉重复的便捷save调用,保留operation相关实现:
let database = CKContainer.default().publicCloudDatabase // 用强引用持有当前上传操作,VC销毁时可以访问到 var currentUploadOperation: CKModifyRecordsOperation? func save(videoURL: URL) { let record = CKRecord(recordType: "MyType") let fileURL = URL(fileURLWithPath: videoURL.path) let asset = CKAsset(fileURL: fileURL) record["videoAsset"] = asset // 初始化操作 let operation = CKModifyRecordsOperation(recordsToSave: [record], recordIDsToDelete: nil) operation.savePolicy = .allKeys // 可选:设置操作的质量优先级,上传大文件建议设为utility operation.qualityOfService = .utility operation.modifyRecordsCompletionBlock = { [weak self] (savedRecordIDs, deletedRecordsIDs, error) in // 页面销毁后回调触发时直接返回 guard let self = self else { return } // 先判断错误类型 if let ckError = error as? CKError, ckError.code == .operationCancelled { // 主动取消触发的回调,直接忽略,不做错误提示 self.currentUploadOperation = nil return } // 这里处理正常的保存成功、非取消类失败逻辑 if let err = error { // 处理其他业务错误 return } // 保存成功逻辑 self.currentUploadOperation = nil } currentUploadOperation = operation database.add(operation) }
在VC销毁、或者用户主动触发取消操作时,调用取消方法即可:
// 统一的取消方法,可以在用户点击关闭/返回按钮、deinit时调用 func cancelCurrentUpload() { currentUploadOperation?.cancel() currentUploadOperation = nil } // 页面销毁时自动取消未完成的上传 deinit { cancelCurrentUpload() }
注意事项
- 调用
cancel()后,已经上传到CloudKit服务器的文件分片不会回滚,但后续上传流程会立刻终止,不会继续占用用户带宽、产生额外流量。 - 取消操作后,操作的completion回调一定会触发,返回
CKError.operationCancelled类型的错误,必须在回调里单独判断这个错误,不要给用户弹出"上传失败"类的提示。 - 不要同时调用便捷
save方法和添加CKModifyRecordsOperation,会导致重复上传同一份数据。
内容的提问来源于stack exchange,提问作者Lance Samaria
相关产品推荐
相关产品推荐

