CloudKit Query (and Dashboard) returns only a few records

When I query, an existing database with over 10,000 records from an Objective C app (i.e. CKQueryOperation) I get only N x 100 records returned where N varies each time between 0 and about 10 (i.e. never more than 1000 records and always an even multiple of 100). When I do a “Query Records” on the CloudKit Dashboard I get a similar number of pages of records downloaded (i.e. 0-10). If I tap “Query Records” multiple times I will get more pages of records until the full 10,000 are downloaded.

This had been working fine until recently, both from the app and the Dashboard. There are multiple Record Types in the database. Only one Record Type is erroring. The other Record Types continue to work both from the app and the Dashboard. In particular, the Users Record Type has many many records and they all download to many pages with a single tap of “Query Records”.

I have posted this to the Feedback Assistant under FB22358865.

Here is my code:

    NSPredicate *predicate =[NSPredicate predicateWithFormat:@"modificationDate>%@",dateLastSynched];
    CKRecordType theRecordName=[NSString stringWithString:@"Notices”]; 
      //  I also try this for @“Links” and @“Messages” and @“EventMessages"
    CKQuery *query = [[CKQuery alloc] initWithRecordType:theRecordName predicate:predicate];
    CKQueryOperation *theOperation=[[CKQueryOperation alloc] initWithQuery:query];
    [self startAQueryOperation:(CKQueryOperation *)theOperation theName:(NSString *)recordName];

-(void)startAQueryOperation:(CKQueryOperation *)theOperation theName:(NSString *)recordName{
	     theOperation.recordFetchedBlock=^(CKRecord *theRecord){
    	         NSLog(@"XXXjust downloaded a %@",recordName);
  	   };
	     theOperation.queryCompletionBlock=^(CKQueryCursor *theCursor, NSError *error){
               if(error){
                    NSLog(@"XXXerror  %@",error);
               }
               if(theCursor){
            	   CKQueryOperation *anotherOperation=[[CKQueryOperation alloc] initWithCursor:theCursor];
            	   [self startAQueryOperation:anotherOperation theName:recordName];
              }
        };
        CKDatabase *publicDatabase = [[CKContainer defaultContainer] publicCloudDatabase];
        [publicDatabase addOperation:theOperation];
}

When I run this code in the app I get no “XXXerror” from the NSLogs. I get the expected number of “XXXjust downloaded a” EventMessages (435) and Messages (594) and Links (15) but I get varying amounts, 100 or 400 or 500 “xxjust downloaded a” for the Notices when I should get 10,118 records. Thinking that 10,000 records is too much, if I alter “dateLastSynched” for Notices I still get only 100 or 200, not the expected number. Note that the number is always a multiple of 100. This seems to be consistent with the typical number of records I get on the CloudKit dashboard each time I tap “Query Records”.

Sorry if this is something that you are already aware of. Take it with a pinch of salt as my knowledge on this is a bit rusty.

Could you check the following?

  • CKQueryOperation.resultsLimit is responsible for the number of record returned. It might be 100, which could be why you get in batches of 100. You can change this value.
  • Is [[CKQueryOperation alloc] initWithCursor:theCursor] is actually getting hit for refetching remaining records ?
  • CKQueryOperation.configuration for qualityOfService. The default qualityOfService might be utility which may not be what you desire. You might need to set it higher qos depending on your needs.

If [[CKQueryOperation alloc] initWithCursor:theCursor] is actually hit but the last one didn't complete then it could be the qualityOfService. Try setting it to userInitiated.

Just curious It is interesting you are using a public database, is this user data stored in public database or common content? If it is private user data, then would be better to use private database. Even the quota for public database would be counted against your app.

  • queryCompletionBlock is deprecated. Use queryResultBlock instead.
  • Also in subsequent CKQueryOperation you create with a cursor, set the resultsLimit. (I think this is optional but if you want to override the default value you could set it)
CloudKit Query (and Dashboard) returns only a few records
 
 
Q