无法在 for 循环中从公共数据库中获取多个 CKReference 记录

Posted

技术标签:

【中文标题】无法在 for 循环中从公共数据库中获取多个 CKReference 记录【英文标题】:Cannot fetch multiple CKReference records from public Database in a for loop 【发布时间】:2020-07-27 03:29:57 【问题描述】:

我有一个联系人 CKRecord,有很多位置 CKRecords(一对多的关系) 联系人 CKRecord 和位置 CKRecord 都是在公共数据库中创建的。我通过 location 上名为 owningContact 的字段将联系人的 CKReference 添加到 locaiotn。

ckRecord["owningContact"] = CKReference(record: contactRecord!, action: .deleteSelf)

我转到 cloudKit 仪表板并验证两条记录都存在。位置 CKRecord 具有字段 owningContact,该字段具有联系人 CKRecord 的记录名称。我定义了一个函数来获取这样的位置:

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($0)
        print($0)
    
    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 发送的,该信息立即返回而无需等待云响应,而 for 循环发送第二个联系并再次调用 iCloudFetchLocations。由于第二个联系人没有对该位置的 CKReference,因此呼叫失败,我永远无法到达第一个联系人的位置,因为它还没有返回。

如何解决这个问题?

【问题讨论】:

【参考方案1】:

我发现我没有设置 CKReference 字段:owningContact 为 Queryable。我发现的方法是这样的打印错误:

 if let ckerror = error as? CKError 
            print(ckerror.userInfo)
            print(ckerror.errorUserInfo)
            self.aErrorHandler.handleCkError(ckerror: ckerror)
  

我一这样做,它就开始工作了,因为我在一个 for 循环中,所以我认为它在之前的 fetch 上超时了。

【讨论】:

以上是关于无法在 for 循环中从公共数据库中获取多个 CKReference 记录的主要内容,如果未能解决你的问题,请参考以下文章

如何在自动生成的for循环中从html表单中获取唯一值

C++ - 在 FOR 循环中从向量获取大小

在基于范围的 for 循环中从 std::vector<Object> 获取指向 Object 的指针

在循环中从一到x获取数字?

在 Swift 的嵌套循环中从特定索引枚举字符串

如何在...循环中从动态列表中打印多个值