【问题标题】:CKQueryOperation queryCompletionBlock only runs 3 timesCKQueryOperation queryCompletionBlock 只运行 3 次
【发布时间】:2015-07-19 16:07:16
【问题描述】:

我正在尝试使用 CloudKit 和光标从我的 iCloud 公共数据库中下载一批记录。无论 resultsLimit 是如何设置的,代码对于前 3 次执行都可以正常工作,但第 4 个完成块永远不会执行。如果未设置 resultsLimit 我得到 300 条记录,如果设置为 50 我得到 150,如果设置为 5 我得到 15...

没有报告错误,并且该块似乎已添加但从未执行。平台是 OS X。这是有问题的代码:

        let queryOp = CKQueryOperation(query: query)
        queryOp.recordFetchedBlock = self.fetchedDetailRecord
        queryOp.resultsLimit = 5
        queryOp.queryCompletionBlock = { [weak self]
          (cursor: CKQueryCursor!, error: NSError!) -> Void in
          println("comp block called with \(cursor) \(error)")
          if error != nil {
            println("Error on fetch \(error.userInfo)")
          } else {
            if cursor != nil {
              let nextOp = CKQueryOperation(cursor: cursor)
              nextOp.recordFetchedBlock = self!.fetchedDetailRecord
              nextOp.queryCompletionBlock = queryOp.queryCompletionBlock
              nextOp.resultsLimit = 5
              self!.publicDatabase?.addOperation(nextOp)
              println("added next fetch")
            } else {
              self!.fileHandle!.closeFile()
              self!.exportProgressIndicator.stopAnimation(self)
            }
          }
        }

        self.publicDatabase?.addOperation(queryOp)

这是来自控制台的结果 -

459013587628.012 0 459013587628.621 1 459013587628.863 2 459013587629.113 3 459013587629.339 4 用 nil 调用的 comp 块 添加了下一次提取 459013587828.552 5 459013587828.954 6 459013587829.198 7 459013587829.421 8 459013587829.611 9 用 nil 调用的 comp 块 添加了下一次提取 459013587997.084 10 459013587997.479 11 459013587997.74 12 459013587997.98 13 459013587998.207 14

大数字只是调用recordFetchedBlock之间的时间,第二个数字是调用该块的次数。

我很难过...关于如何继续的任何想法?哦,container和publicDatabase都是类变量,在运行上面的sn-p代码之前进行了初始化。

【问题讨论】:

    标签: macos swift cloudkit


    【解决方案1】:

    您在 queryCompletionBlock 范围内定义 nextOp 的方式在该块的三次迭代后会导致问题。如果您将 CKQueryOperation 的创建分解为它自己的方法,您的问题就会消失。

    代码如下:

    func fetchedDetailRecord(record: CKRecord!) -> Void {
        println("Retrieved record: \(record)")
    }
    
    func createQueryOperation(cursor: CKQueryCursor? = nil) -> CKQueryOperation {
        var operation:CKQueryOperation
        if (cursor != nil) {
            operation = CKQueryOperation(cursor: cursor!)
        } else {
            operation = CKQueryOperation(query: CKQuery(...))
        }
        operation.recordFetchedBlock = self.fetchedDetailRecord
        operation.resultsLimit = 5
        operation.queryCompletionBlock = { [weak self]
            (cursor: CKQueryCursor!, error: NSError!) -> Void in
            println("comp block called with \(cursor) \(error)")
            if error != nil {
                println("Error on fetch \(error.userInfo)")
            } else {
                if cursor != nil {
                    self!.publicDatabase?.addOperation(self!.createQueryOperation(cursor: cursor))
                    println("added next fetch")
                } else {
                    self!.fileHandle!.closeFile()
                    self!.exportProgressIndicator.stopAnimation(self) 
                }
            }
        }
        return operation
    }
    
    func doQuery() {
        println("Querying records...")
        self.publicDatabase?.addOperation(createQueryOperation())
    }
    

    【讨论】:

    • 感谢 Dave,很抱歉花了这么长时间才回复,但您的回复已经结束。一旦我将它移到它自己的函数中,查询就会完美运行。
    • 谢谢!但是,似乎 operation.cursor = cursor 并没有使操作以光标开始;而是使用 operation = CKQueryOperation(cursor: cursor) 为我工作 - 想法?
    • 啊,很好。文档确实说“当您使用游标时,查询属性的内容将被忽略”,因此我相应地更新了代码示例。
    • 这个解决方案有一个主要缺点,但是:初始操作将在所有子操作完成之前结束。因此,我们不能将它用于操作之间的依赖关系:-( 我尝试使用 addOperations(:waitUntilFinished) 而不是 addOperation() 但是......它在三次迭代后停止。有什么想法吗?
    【解决方案2】:

    这可能是另一种方法(已经更新到 Swift 3)。

    第三次迭代后不会停止,而是一直持续到结束

    var queryOp = CKQueryOperation(query: query)
    queryOp.recordFetchedBlock = self.fetchedARecord
    queryOp.resultsLimit = 5
    queryOp.queryCompletionBlock = { [weak self] (cursor : CKQueryCursor?, error : Error?) -> Void in
        print("comp block called with \(cursor) \(error)")
    
        if cursor != nil {
            let nextOp = CKQueryOperation(cursor: cursor!)
            nextOp.recordFetchedBlock = self!.fetchedARecord
            nextOp.queryCompletionBlock = queryOp.queryCompletionBlock
            nextOp.resultsLimit = queryOp.resultsLimit
    
            //this is VERY important
            queryOp = nextOp
    
            self!.publicDB.add(queryOp)
            print("added next fetch")
        }
    
    }
    
    self.publicDB.add(queryOp)
    

    我成功地用它从 CloudKit 中检索了数百条记录

    【讨论】:

    • 我遇到了同样的问题,您的评论“这非常重要”解决了这个问题。我要补充的是你强调它的重要性的那一行。你让我今天一整天都感觉很好。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-18
    • 2011-12-13
    • 2017-10-17
    • 2013-11-13
    相关资源
    最近更新 更多