CloudKit 查询操作只返回 300 个结果

Posted

技术标签:

【中文标题】CloudKit 查询操作只返回 300 个结果【英文标题】:CloudKit Query Operation only returns 300 results 【发布时间】:2016-02-22 12:14:40 【问题描述】:

我目前正在将 CloudKit 设置为 Parse 的替代品,并且需要下载我的所有用户记录。我目前有大约 600 条记录,但我只收到 300 条。

我正在使用一个名为“用户”的自定义记录区域,而不是默认的“用户”记录区域,因为此应用只会绑定到一个 appID。

我使用的代码基于对以下问题的回答,但它不适用于我。当光标为 nil 时,查询操作似乎不会运行,因为 print(userArray) 从未被调用。提前感谢您的帮助!

CKQuery from private zone returns only first 100 CKRecords from in CloudKit

func queryAllUsers() 

    let database = CKContainer.defaultContainer().privateCloudDatabase
    let query = CKQuery(recordType: "User", predicate: NSPredicate(value: true))
    let queryOperation = CKQueryOperation(query: query)
    queryOperation.recordFetchedBlock = self.createUserObject

    queryOperation.queryCompletionBlock =  cursor, error in

        if cursor != nil 
            print("there is more data to fetch")
            let newOperation = CKQueryOperation(cursor: cursor!)
            newOperation.recordFetchedBlock = self.createUserObject
            newOperation.queryCompletionBlock = queryOperation.queryCompletionBlock
            database.addOperation(newOperation)

         else 

            print(userArray) //Never runs
        
    

    database.addOperation(queryOperation)



func createUserObject(record: CKRecord) 
    let name = record.objectForKey("Name") as! String!
    let company = record.objectForKey("Company") as! String!
    let dateInductionCompleted = record.objectForKey("DateInductionCompleted") as! NSDate!
    var image = UIImage()

    let imageAsset = record.objectForKey("Image") as! CKAsset!
    if let url = imageAsset.fileURL as NSURL? 
        let imageData = NSData(contentsOfURL:url)
        let mainQueue = NSOperationQueue.mainQueue()
        mainQueue.addOperationWithBlock() 
            image = UIImage(data: imageData!)!
            userArray.append(User(name: name, company: company, image: image, dateInductionCompleted: dateInductionCompleted))
        
    
    print(userArray.count)

更新

问题已得到解答,这可能是使用游标进行大型查询时的固有错误。该代码现在使用递归函数工作,工作代码如下:

func queryRecords() 

    let database = CKContainer.defaultContainer().privateCloudDatabase
    let query = CKQuery(recordType: "User", predicate: NSPredicate(value: true))
    let queryOperation = CKQueryOperation(query: query)
    queryOperation.qualityOfService = .UserInitiated
    queryOperation.recordFetchedBlock = populateUserArray

    queryOperation.queryCompletionBlock =  cursor, error in

        if cursor != nil 
            print("There is more data to fetch")
            self.fetchRecords(cursor!)
        
    
    database.addOperation(queryOperation)



func fetchRecords(cursor: CKQueryCursor?) 

    let database = CKContainer.defaultContainer().privateCloudDatabase
    let queryOperation = CKQueryOperation(cursor: cursor!)
    queryOperation.qualityOfService = .UserInitiated
    queryOperation.recordFetchedBlock = populateUserArray

    queryOperation.queryCompletionBlock =  cursor, error in

        if cursor != nil 
            print("More data to fetch")
            self.fetchRecords(cursor!)

         else 
            print(userArray)
        
    

    database.addOperation(queryOperation)


func populateUserArray(record: CKRecord) 

    let name = record.objectForKey("Name") as! String!
    let company = record.objectForKey("Company") as! String!
    let dateInductionCompleted = record.objectForKey("DateInductionCompleted") as! NSDate!
    var image = UIImage()

    let imageAsset = record.objectForKey("Image") as! CKAsset!
    if let url = imageAsset.fileURL as NSURL? 
        let imageData = NSData(contentsOfURL:url)
        let mainQueue = NSOperationQueue.mainQueue()
        mainQueue.addOperationWithBlock() 
            image = UIImage(data: imageData!)!
            userArray.append(User(name: name, company: company, image: image, dateInductionCompleted: dateInductionCompleted))
        
    
    print(userArray.count)

【问题讨论】:

【参考方案1】:

你能不能试试设置:

queryOperation.qualityOfService = .UserInitiated

这表明您的用户交互需要数据。 否则可能会导致 de 请求被完全忽略。

如下所述,实际答案是您不应该重复使用完成块。相反,您应该创建一个递归函数来从游标中获取下一条记录。可以在以下位置找到一个示例:EVCloudKitDao

【讨论】:

谢谢,我已经在 queryOperation 和 newOperation 上试过了,但它仍然停留在 300。还有什么我可以尝试的吗? 当您尝试在新操作中重用完成块时,我已经看到光标出现问题。在这里你可以看到我有一个单独的函数用于带有可以递归调用的游标的查询:github.com/evermeer/EVCloudKitDao/blob/… 效果很好,谢谢!!您是否想使用该信息更新您的答案,我会将其标记为已回答。我也会将我的工作代码添加到我的问题中。

以上是关于CloudKit 查询操作只返回 300 个结果的主要内容,如果未能解决你的问题,请参考以下文章

限制 CloudKit 中返回的结果数量

CloudKit 查询与 modifyDate 始终返回无结果

Apple CloudKit 分页

如何限制从 NSMetadataQuery 返回的结果数量?

CloudKit 批量获取?

如何从 CloudKit 查询和获取数据?