iosswiftcloudkitckrecordckqueryoperation

Can't have more than 100 records in CloudKit


I have tried many different ways to fetch records and checked the same problems on stackoverflow but can't have more than 100 records fetched.

Before, I was using CKQuery instead of CKQueryOperation to use the resultsLimit parameter.

Here is my code:

    func initData(){
        // show activity indicator
        self.activityIndicatorView.hidden = false
        // hide connection error button
        self.connectionErrorButton.hidden = true

        let container = CKContainer.defaultContainer()
        let publicDB = container.publicCloudDatabase

        let predicate = NSPredicate(value: true)
        let sort = NSSortDescriptor(key: "id", ascending: true)

        var newInfo = Array<CKRecord>()

        let query = CKQuery(recordType: "info", predicate:  predicate)
        query.sortDescriptors = [sort]

        let queryOperation = CKQueryOperation(query: query)
        queryOperation.queuePriority = .VeryHigh
        queryOperation.resultsLimit = 150;

        // Fetch the pokemons for the record
        func fetched(record: CKRecord!) {
            newInfo.append(record)
        }

        queryOperation.recordFetchedBlock = fetched

        queryOperation.queryCompletionBlock = { [unowned self] (cursor, error) in
            if (error != nil) {
                dispatch_async(dispatch_get_main_queue()) {
                    self.connectionErrorButton.hidden = false
                    self.activityIndicatorView.hidden = true
                    return
                }
            } else {
                dispatch_async(dispatch_get_main_queue()) {
                    self.infos.removeAll()
                    self.infos = newInfo
                    self.tableView.reloadData()
                    self.activityIndicatorView.hidden = true
                    return
                }
            }
        }
        publicDB.addOperation(queryOperation)
    }

Solution

  • On iOS 9.3 and below you'll need to use CKQueryCursor to perform multiple fetch operations and keep track of where you were at in the fetch. Thats the cursor object that got passed back in the completion block, you can create another operation with it which will pick up off where you left it like so:

    queryOperation.queryCompletionBlock = { (cursor, error) in
        if let cursor = cursor {
             let cursorOperation = CKQueryOperation(cursor: cursor)
             cursorOperation.queryCompletionBlock = //Handle it again
        }
        //Do stuff
    }
    

    Often you'll want to make reusable handler blocks when working with cursors so you can recursively create cursor based query operations if more than one arrives.