未调用 CKQueryOperation queryCompletionBlock

CKQueryOperation queryCompletionBlock not called

我使用的 CKQueryOperation 显然对我的大多数用户都适用。但是,对于其中一些人来说,它不起作用。问题是 queryCompletionBlock 没有被调用。

分析用户日志我可以看到它对大多数用户都有效,但对其中一些用户无效。它在所有类型的 iPhone 模型中都失败了。但是 iOS 在故障设备上始终是 iOS 14.2。不幸的是,我无法在我的设备上重现该问题,因此无法对其进行调试。

我已经检查过该问题与互联网连接类型(wifi 或数据)无关

有什么想法吗?

这是代码

func fetchTeams(_ success: @escaping (_ result: [CKRecord]?) -> Void,
                       failure: @escaping (_ error: NSError) -> Void) {
        
        bfprint("fetchTeams starts")
        let type = RecordType.Team
        let predicate = NSPredicate(format: "TRUEPREDICATE")
        let query = CKQuery(recordType: type.rawValue, predicate: predicate)
        let operation = CKQueryOperation(query: query)
        allTeamsRecords = []
        executeQueryOperation(operation,
                                   success: success,
                                   failure: failure)
    }
    
    private func executeQueryOperation(_ queryOperation: CKQueryOperation,
                                              success: @escaping (_ result: [CKRecord]?) -> Void,
                                              failure: @escaping (_ error: NSError) -> Void) {
        
        bfprint("executeQueryOperation starts")
        
        let configuration = CKOperation.Configuration()
        configuration.qualityOfService = .userInitiated
        queryOperation.configuration = configuration
        queryOperation.queuePriority = .veryHigh

        queryOperation.recordFetchedBlock = { [weak self] (record) in
            guard let strongSelf = self else {
                bfprint("CloudKitDataProvider was deallocated before we got all team records")
                return
            }
            strongSelf.allTeamsRecords.append(record)
        }
        
        queryOperation.queryCompletionBlock = { [weak self] (cursor, error) in
            bfprint("fetch teams operation completion block called")
            if let cursor = cursor {
                bfprint("We got a new cursor fetching teams")
                let newOperation = CKQueryOperation(cursor: cursor)
                guard let strongSelf = self else {
                    bfprint("CloudKitDataProvider was deallocated before we got all team records")
                    return
                }
                strongSelf.executeQueryOperation(newOperation,
                                           success: success,
                                           failure: failure)
            }
            else if let error = error {
                DispatchQueue.main.async(execute: {
                    failure(error as NSError)
                    bfprint("Cloud Query Error - Fetching Teams): \(error)")
                })
            }
            else {
                DispatchQueue.main.async(execute: {
                    bfprint("Get teams finished successfully")
                    guard let strongSelf = self else {
                        bfprint("CloudKitDataProvider was deallocated before we execute success closure")
                        return
                    }
                    success(strongSelf.allTeamsRecords)
                })
            }
        }
        Self.publicDB.add(queryOperation)
        bfprint("query added to database")
    }

我不知道你的情况具体有什么问题,但我可能会提供一些关于 CloudKit 的一般指导,因为我多年来一直在使用它。 CloudKit确实靠谱,但也有点不靠谱。 :)

这里有一些提示:

  • 内置重复检查您是否拥有最新数据的机制。
  • 后台通知并不总是出现。有办法获取可能遗漏的数据。
  • 开发和生产的行为略有不同,因为开发似乎总体上不太可靠。
  • CloudKit 仪表板需要不时刷新(就像网络浏览器中的整个页面一样),因为即使使用界面中的重新加载和查询按钮,显示的状态也会变得陈旧.

因此,在您的情况下,您可能有一种方法可以重复尝试 CKQueryOperation,以便在 CloudKit 出现问题时重新尝试。维护与 CloudKit 同步的本地缓存是我发现确保数据准确的最佳方法。

我 99% 确定这是一个 iOS 问题。用户更新到 iOS 14.3 后问题消失了