CKQueryOperation queryCompletionBlock 只运行 3 次
Posted
技术标签:
【中文标题】CKQueryOperation queryCompletionBlock 只运行 3 次【英文标题】:CKQueryOperation queryCompletionBlock only runs 3 times 【发布时间】: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代码之前进行了初始化。
【问题讨论】:
【参考方案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 中检索了数百条记录
【讨论】:
我遇到了同样的问题,您的评论“这非常重要”解决了这个问题。我要补充的是你强调它的重要性的那一行。你让我今天一整天都感觉很好。谢谢!以上是关于CKQueryOperation queryCompletionBlock 只运行 3 次的主要内容,如果未能解决你的问题,请参考以下文章
使用 CKQueryOperation 和 CKReference 获取大集合
CloudKit:删除记录的 CKQueryOperation
CloudKit - 具有依赖关系的 CKQueryOperation