首页 > 解决方案 > CKQueryOperation queryCompletionBlock 未调用

问题描述

我正在使用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")
    }

标签: ioscloudkit

解决方案


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

以下是一些提示:

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

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


推荐阅读