iosswiftcloudkitckqueryoperation

How do I use CloudKit to query iteratively with CKQueryOperation until cursor is nil?


How would I declare a closure that retrieves records from CloudKit that iteratively calls itself until all the records are fetched? The following code does that, except I get an error saying

Variable used within its own initial value

at the line where I assign the closure queryCompletionBlock to the property by that same name of the query operation within the declaration of the closure itself. Basically, I get an error because I call the closure within itself in the declaration of the closure before the closure is declared.

    let predicate = NSPredicate(value: true)
    let query = CKQuery(recordType: DatabaseNameStrings.recordTypeEntry, predicate: predicate)
    let queryOperation = CKQueryOperation(query: query)
    queryOperation.desiredKeys = [DatabaseNameStrings.fieldNameCreatedAt, DatabaseNameStrings.fieldNameText]
    let queryCompletionBlock = {
        (cursor: CKQueryOperation.Cursor?, error: Error?) in
        if let error = error {
            print(error.localizedDescription)
        } else if let cursor = cursor {
            let queryOperation = CKQueryOperation(cursor: cursor)
            queryOperation.desiredKeys = [DatabaseNameStrings.fieldNameCreatedAt, DatabaseNameStrings.fieldNameText]
            queryOperation.queryCompletionBlock = queryCompletionBlock // Error message "Variable used within its own initial value"
            queryOperationQueue.addOperation(queryOperation)
        }
    }
    queryOperation.queryCompletionBlock = queryCompletionBlock
    queryOperationQueue.addOperation(queryOperation)

Solution

  • One option that should work is to reference the queryCompletionBlock of the original query operation.

    let predicate = NSPredicate(value: true)
    let query = CKQuery(recordType: DatabaseNameStrings.recordTypeEntry, predicate: predicate)
    let queryOperation = CKQueryOperation(query: query)
    queryOperation.desiredKeys = [DatabaseNameStrings.fieldNameCreatedAt, DatabaseNameStrings.fieldNameText]
    let queryCompletionBlock = {
        (cursor: CKQueryOperation.Cursor?, error: Error?) in
        if let error = error {
            print(error.localizedDescription)
        } else if let cursor = cursor {
            let newOperation = CKQueryOperation(cursor: cursor)
            newOperation.desiredKeys = queryOperation.desiredKeys
            newOperation.queryCompletionBlock = queryOperation.queryCompletionBlock
            newOperationQueue.addOperation(newOperation)
        }
    }
    queryOperation.queryCompletionBlock = queryCompletionBlock
    queryOperationQueue.addOperation(queryOperation)