CloudKit 仅查询操作 returns 300 个结果

CloudKit Query Operation only returns 300 results

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

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

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

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

能否尝试设置:

queryOperation.qualityOfService = .UserInitiated

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

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