How would I declare a closure that retrieves records from CloudKit that iteratively calls itself until all the records are fetched?

How do I write code that repeatedly runs a query operation until all the records of that record type are retrieved?


I tried iteratively calling a closure within itself, but I would have to use the closure in the declaration of the closure itself. Thus the closure is called within its declaration before it is declared.


Here is my code. I put a comment saying the error where the error occurs.


        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)

Accepted Reply

You have to wrap the addOperation this way:

        let predicate = NSPredicate(value: true)  
        let query = CKQuery(recordType: DatabaseNameStrings.recordTypeEntry, predicate: predicate)  
        let queryOperation = CKQueryOperation(query: query)  
        queryOperation.desiredKeys = [DatabaseNameStrings.fieldNameCreatedAt, DatabaseNameStrings.fieldNameText]





//  at this point call lines below in a new method by passing in the object queryOperation


        let queryCompletionBlock = {  
            (cursor: CKQueryOperation.Cursor?, error: Error?) in  
            if let error = error {  
                print(error.localizedDescription)  
            } else if let cursor = cursor { 
//  at this point, create a new queryOperation2 using something like initWithCursor:cursor
//        and then call this method passing in that new queryOperation2
//       and don't do any of the next 4 lines
                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) 

Replies

You have to wrap the addOperation this way:

        let predicate = NSPredicate(value: true)  
        let query = CKQuery(recordType: DatabaseNameStrings.recordTypeEntry, predicate: predicate)  
        let queryOperation = CKQueryOperation(query: query)  
        queryOperation.desiredKeys = [DatabaseNameStrings.fieldNameCreatedAt, DatabaseNameStrings.fieldNameText]





//  at this point call lines below in a new method by passing in the object queryOperation


        let queryCompletionBlock = {  
            (cursor: CKQueryOperation.Cursor?, error: Error?) in  
            if let error = error {  
                print(error.localizedDescription)  
            } else if let cursor = cursor { 
//  at this point, create a new queryOperation2 using something like initWithCursor:cursor
//        and then call this method passing in that new queryOperation2
//       and don't do any of the next 4 lines
                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)