简体   繁体   English

CKQueryOperation queryCompletionBlock 未调用

[英]CKQueryOperation queryCompletionBlock not called

I'm using a CKQueryOperation that apparently works fine for most of my users.我使用的CKQueryOperation显然适用于我的大多数用户。 However, for some of them it is not working.但是,对于其中一些人来说,它不起作用。 The issue is that queryCompletionBlock is not being called.问题是queryCompletionBlock没有被调用。

Analysing user logs I can see that it works fine for most of the users, but it doesn't work for a few of them.分析用户日志我可以看到它对大多数用户都有效,但对其中一些用户不起作用。 It fails in all kind of iPhone models.它在所有类型的 iPhone 型号中都失败了。 But iOS is always iOS 14.2 on the failing devices.但 iOS 在故障设备上始终为 iOS 14.2。 Unfortunately, I can not reproduce the issue on my device and this makes impossible to debug it.不幸的是,我无法在我的设备上重现该问题,因此无法对其进行调试。

I've already checked that the issue is not related with the internet connection type (wifi or data)我已经检查过该问题与互联网连接类型(wifi 或数据)无关

Any idea?任何想法?

This is the code这是代码

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")
    }

I don't know what's specifically wrong in your situation, but I might offer some general guidance with CloudKit as I've worked with it over the years.我不知道您的情况具体出了什么问题,但我可能会提供一些关于 CloudKit 的一般指导,因为我多年来一直在使用它。 CloudKit is really reliable, but it's also a little unreliable. CloudKit 确实可靠,但也有点不可靠。 :) :)

Here are some tips:以下是一些提示:

  • Build in mechanisms to repeatedly check that you have the latest data.内置机制以反复检查您是否拥有最新数据。
  • Background notifications don't always come.后台通知并不总是出现。 Have a way to get data that may have been missed.有办法获取可能丢失的数据。
  • Development and production behave a little differently in that dev seems to be a bit less reliable overall.开发和生产的行为略有不同,因为开发似乎总体上不太可靠。
  • The CloudKit Dashboard needs to be refreshed (like the whole page in your web browser) from time-to-time because the state shown can get stale even when using the reload and query buttons in the interface. CloudKit 仪表板需要不时刷新(如 web 浏览器中的整个页面),因为即使使用界面中的重新加载和查询按钮,显示的 state 也会变得陈旧。

So in your case, you might have a way to repeatedly try the CKQueryOperation so that it gets reattempted if something is haywire on CloudKit.因此,在您的情况下,您可能有办法重复尝试CKQueryOperation ,以便在 CloudKit 出现问题时重新尝试。 Maintaining a local cache that syncs with CloudKit is the best way I've found to make sure your data is accurate.维护与 CloudKit 同步的本地缓存是我发现确保数据准确的最佳方法。

I'm 99% sure it was an iOS issue.我 99% 确定这是 iOS 问题。 After users updated to iOS 14.3 the problem disappeared用户更新到 iOS 14.3 后问题消失了

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM