无法在 for 循环中从 public 数据库中获取多个 CKReference 记录
Cannot fetch multiple CKReference records from public Database in a for loop
我有一个联系人 CKRecord 有很多位置 CKRecords(一对多关系)
联系人 CKRecord 和位置 CKRecord 都在 public 数据库中创建。我通过位置上名为 owningContact 的字段将联系人的 CKReference 添加到 locaiotn。
ckRecord["owningContact"] = CKReference(record: contactRecord!, action: .deleteSelf)
我转到 cloudKit 仪表板并验证这两条记录是否存在。位置 CKRecord 具有字段 owningContact,该字段具有联系人 CKRecord 的 recordName。我定义了一个函数来获取这样的位置:
private func iCloudFetchLocations(withContactCKRecord: CKRecord, completionHandler: @escaping ([CKRecord]?, Error?) -> Void) {
var records = [CKRecord]()
let recordToMatch = CKReference(recordID: withContactCKRecord.recordID, action: .deleteSelf)
let predicate = NSPredicate(format: "owningContact == %@", recordToMatch)
// Create the query object.
let query = CKQuery(recordType: "location", predicate: predicate)
let queryOp = CKQueryOperation(query: query)
queryOp.resultsLimit = 1
queryOp.qualityOfService = .userInteractive
queryOp.recordFetchedBlock = {
records.append([=12=])
print([=12=])
}
queryOp.queryCompletionBlock = { (cursor, error) in
guard error == nil else {
if let ckerror = error as? CKError {
self.aErrorHandler.handleCkError(ckerror: ckerror)
}
return
}
if (cursor != nil) {
let newOperation = CKQueryOperation(cursor: cursor!)
newOperation.resultsLimit = queryOp.resultsLimit
newOperation.recordFetchedBlock = queryOp.recordFetchedBlock
newOperation.queryCompletionBlock = queryOp.queryCompletionBlock
self.publicDB?.add(newOperation)
}
completionHandler(records, error)
}
self.publicDB?.add(queryOp)
}
然后我调用代码根据联系人 CKRecord 获取位置 CKRecord,如下所示:
let predicate = NSPredicate(format: "TRUEPREDICATE")
let query = CKQuery(recordType: Cloud.Entity.Contact, predicate: predicate)
publicDB?.perform(query, inZoneWith: nil, completionHandler: { (records, error) in
guard error == nil else {
if let ckerror = error as? CKError {
self.aErrorHandler.handleCkError(ckerror: ckerror)
}
return
completion(false)
}
if let contactRecords = records {
for aContactRecord in contactRecords {
// fetch Location Data
self.iCloudFetchLocations(withContactCKRecord: aContactRecord, completionHandler: { records, error in
guard error == nil else {
if let ckerror = error as? CKError {
self.aErrorHandler.handleCkError(ckerror: ckerror)
}
return
completion(false)
}
if let locationRecords = records {
}
})
}
}
})
我有两个联系人,第一个已被 CKReferenc'ed 到该位置,而第二个联系人仍未被 CKReferenc'ed 到该位置。
我认为这是问题所在:循环中的第一次联系 CKRecord 信息是通过立即调用 iCloudFetchLocations 发送的 returns 而无需等待云响应,并且 for 循环发送第二个联系并再次调用 iCloudFetchLocations。由于第二个联系人没有位置的 CKReference,调用失败,我永远无法到达第一个联系人的位置,因为它还没有返回。
如何解决这个问题?
我发现我没有将 CKReference 字段:owningContact 设置为 Queryable。我发现的方式是这样的打印错误:
if let ckerror = error as? CKError {
print(ckerror.userInfo)
print(ckerror.errorUserInfo)
self.aErrorHandler.handleCkError(ckerror: ckerror)
}
我一这样做它就开始工作了,因为我在一个 for 循环中,我认为它在上一次获取时超时了。
我有一个联系人 CKRecord 有很多位置 CKRecords(一对多关系) 联系人 CKRecord 和位置 CKRecord 都在 public 数据库中创建。我通过位置上名为 owningContact 的字段将联系人的 CKReference 添加到 locaiotn。
ckRecord["owningContact"] = CKReference(record: contactRecord!, action: .deleteSelf)
我转到 cloudKit 仪表板并验证这两条记录是否存在。位置 CKRecord 具有字段 owningContact,该字段具有联系人 CKRecord 的 recordName。我定义了一个函数来获取这样的位置:
private func iCloudFetchLocations(withContactCKRecord: CKRecord, completionHandler: @escaping ([CKRecord]?, Error?) -> Void) {
var records = [CKRecord]()
let recordToMatch = CKReference(recordID: withContactCKRecord.recordID, action: .deleteSelf)
let predicate = NSPredicate(format: "owningContact == %@", recordToMatch)
// Create the query object.
let query = CKQuery(recordType: "location", predicate: predicate)
let queryOp = CKQueryOperation(query: query)
queryOp.resultsLimit = 1
queryOp.qualityOfService = .userInteractive
queryOp.recordFetchedBlock = {
records.append([=12=])
print([=12=])
}
queryOp.queryCompletionBlock = { (cursor, error) in
guard error == nil else {
if let ckerror = error as? CKError {
self.aErrorHandler.handleCkError(ckerror: ckerror)
}
return
}
if (cursor != nil) {
let newOperation = CKQueryOperation(cursor: cursor!)
newOperation.resultsLimit = queryOp.resultsLimit
newOperation.recordFetchedBlock = queryOp.recordFetchedBlock
newOperation.queryCompletionBlock = queryOp.queryCompletionBlock
self.publicDB?.add(newOperation)
}
completionHandler(records, error)
}
self.publicDB?.add(queryOp)
}
然后我调用代码根据联系人 CKRecord 获取位置 CKRecord,如下所示:
let predicate = NSPredicate(format: "TRUEPREDICATE")
let query = CKQuery(recordType: Cloud.Entity.Contact, predicate: predicate)
publicDB?.perform(query, inZoneWith: nil, completionHandler: { (records, error) in
guard error == nil else {
if let ckerror = error as? CKError {
self.aErrorHandler.handleCkError(ckerror: ckerror)
}
return
completion(false)
}
if let contactRecords = records {
for aContactRecord in contactRecords {
// fetch Location Data
self.iCloudFetchLocations(withContactCKRecord: aContactRecord, completionHandler: { records, error in
guard error == nil else {
if let ckerror = error as? CKError {
self.aErrorHandler.handleCkError(ckerror: ckerror)
}
return
completion(false)
}
if let locationRecords = records {
}
})
}
}
})
我有两个联系人,第一个已被 CKReferenc'ed 到该位置,而第二个联系人仍未被 CKReferenc'ed 到该位置。 我认为这是问题所在:循环中的第一次联系 CKRecord 信息是通过立即调用 iCloudFetchLocations 发送的 returns 而无需等待云响应,并且 for 循环发送第二个联系并再次调用 iCloudFetchLocations。由于第二个联系人没有位置的 CKReference,调用失败,我永远无法到达第一个联系人的位置,因为它还没有返回。
如何解决这个问题?
我发现我没有将 CKReference 字段:owningContact 设置为 Queryable。我发现的方式是这样的打印错误:
if let ckerror = error as? CKError {
print(ckerror.userInfo)
print(ckerror.errorUserInfo)
self.aErrorHandler.handleCkError(ckerror: ckerror)
}
我一这样做它就开始工作了,因为我在一个 for 循环中,我认为它在上一次获取时超时了。