I am trying to query all the records of a specified RecordType in my CloudKit database. Because I may have more than 100 records of that type, I am using CloudKit cursors, which return records in batches until there are no more records to return (at which point the cursor is nil).
I save the number of records created on each creationDate. I am getting much higher numbers for each date than there are records in the CloudKit dashboard for those dates. For example, on one day when I count 110 records by hand on the CloudKit dashboard, my code says there are 256. On another day where I count 2, my code says there are 7.
Issues I've considered
- Time zones differences - unlikely because these high counts occur even on days where there are no records created for several days before and after.
- Maybe I'm counting the same records multiple times - I printed out the list of all 472 records that CloudKit found across all the cursor queries. From some testing, it would appear that there are not any record ID duplicates in that list, and all of the records are of the proper type. (Which seems so weird that I wonder if I need to look at that list more.)
- Maybe there's something I'm misunderstanding with my use of cursors. Hence, this StackOverflow post.
Here's my code for how I'm working with cursors. If anyone sees anything off, please let me know!
// This is the main code that kicks off the cursor handling
let predicate = NSPredicate(value: true)
let query = CKQuery(recordType: recordType, predicate: predicate)
let sort = NSSortDescriptor(key: "creationDate", ascending: true) // so the 0th result is the earliest
query.sortDescriptors = [sort]
let operation1 = CKQueryOperation(query: query)
operation1.resultsLimit = 5
operation1.queryCompletionBlock = { (cursor, error) in
if error != nil {
self.recordTypeErrorHandling(error: error as! CKError, uid: uid, appID: appID, recordType: recordType)
}
else {
self.queryRecordsWithCursor(cursor: cursor, isFirstCheck: true, uid: uid, appID: appID, recordType: recordType)
}
CKContainer.default().publicCloudDatabase.add(operation1)
// Related functions
// adapted from: https://gist.github.com/evermeer/5df7ad1f8db529893f40
func queryRecordsWithCursor(cursor: CKQueryCursor?, isFirstCheck: Bool, uid: String, appID: String, recordType: String) {
guard let theCursor = cursor else { return }
let operation = CKQueryOperation(cursor: theCursor)
// happens each time a record is received
operation.recordFetchedBlock = { [recordType] record in
if self.recordTypeToRecordListDict[recordType] == nil {
self.recordTypeToRecordListDict[recordType] = [record]
}
else {
self.recordTypeToRecordListDict[recordType]?.append(record)
}
}
// happens when all records are done for that cursor
operation.queryCompletionBlock = { [recordType] cursor, error in
if error == nil {
if cursor == nil { // cursor is nil => we've gotten all records, so save them
self.saveRecordCounts(records: self.recordTypeToRecordListDict[recordType]!, uid: uid, appID: appID, recordType: recordType, isFirstCheck: isFirstCheck) // use isFirstCheck, not the value in the dictionary
}
else if self.recordTypeToRecordListDict[recordType] != nil {
self.queryRecordsWithCursor(cursor: cursor, isFirstCheck: isFirstCheck, uid: uid, appID: appID, recordType: recordType) // recursive call. if we've gotten here, there's definitely a non-nil cursor
}
}
else {
self.recordTypeErrorHandling(error: error as! CKError, uid: uid, appID: appID, recordType: recordType)
}
}
CKContainer.default().publicCloudDatabase.add(operation)
}
Please let me know if you need more of my code than this! Thank you!
P.S. For what it's worth, when I step through with the debugger, setting the results limit to 5 had no effect. Not sure if that's a related issue.