我正在使用 CloudKit 从使用 CKQuery 的私有数据库中检索记录,在异步函数中使用 CKQueryOperation.queryResultBlock。我已经找到了几个使用 queryCompletionBlock 的示例,但这些示例已被弃用并被 queryResultBlock 取代,关于如何实现它的可用文档很少。只要不返回查询完成游标(<=100 条记录),我的函数就可以很好地工作,但我无法弄清楚如何迭代它。
这是我正在使用的代码:
public func queryRecords(recordType: CKRecord.RecordType, predicate: NSPredicate) async throws -> [CKRecord] {
var resultRecords: [CKRecord] = []
let db = container.privateCloudDatabase
let query = CKQuery(recordType: recordType, predicate: predicate)
let operation = CKQueryOperation(query: query)
let operationQueue = OperationQueue() // for > 100 records
operationQueue.maxConcurrentOperationCount = 1 // for > 100 records
operation.zoneID = zoneID
debugPrint("query for recordType=\(recordType) in zone \(zoneID.zoneName) with predicate \(predicate)")
return try await withCheckedThrowingContinuation { continuation in
operation.queryResultBlock = { result in
switch result {
case .failure(let error):
debugPrint(error)
continuation.resume(throwing: error)
case .success(let ckquerycursor):
debugPrint("successful query completion after \(resultRecords.count) record(s) returned")
if let ckquerycursor = ckquerycursor {
debugPrint("***** received a query cursor, need to fetch another batch! *****")
let newOperation = CKQueryOperation(cursor: ckquerycursor) // for > 100 records
newOperation.queryResultBlock = operation.queryResultBlock // for > 100 records
newOperation.database = db // for > 100 records
operationQueue.addOperation(newOperation) // for > 100 records
}
continuation.resume(returning: resultRecords)
}
}
operation.recordMatchedBlock = { (recordID, result1) in
switch result1 {
case .failure(let error):
debugPrint(error)
case .success(let ckrecord):
resultRecords.append(ckrecord)
}
}
db.add(operation)
}
}
我试图实现类似示例中的代码但没有成功:上面的代码导致致命错误“SWIFT TASK CONTINUATION MISUSE”作为该行
continuation.resume(returning: resultRecords)
显然被多次调用(非法)。用“// for > 100 records”注释的行代表我添加到迭代的代码;其他一切都适用于 100 或更少的记录集。
我是否需要迭代地调用 queryRecords 函数本身,如果它存在则传递查询游标,或者是否可以像我在这里尝试做的那样将迭代操作添加到队列中?
如果有人在使用 queryResultBlock(不推荐使用 queryCompletionBlock)之前这样做过,请帮忙!谢谢!