CloudKit Query with modificationDate Always Returns No Results

218 Views Asked by At

My goal is to get User records from CloudKit I specify in an array of CKRecord.IDs, but only if they were updated more recently than my last updated date which I track locally.

I'm doing the following CloudKit query:

var predicate:NSPredicate

if let lastChecked = defaults.object(forKey: "lastUserFetch") as? Date{
  //Subsequent fetches
  predicate = NSPredicate(format: "modificationDate > %@ AND recordID IN %@", argumentArray: [lastChecked, userRecordIDs])

}else{
  //First fetch
  predicate = NSPredicate(format: "recordID IN %@", argumentArray: [userRecordIDs])
}

let query = CKQuery(recordType: "User", predicate: predicate)
let operation = CKQueryOperation(query: query)
...

I initially set lastUserFetch to nil when my app launches, and the "First fetch" part of the query succeeds. I get all the user records back.

But once I set my lastUserFetch date after the query is done:

defaults.set(Date(), forKey: "lastUserFetch")

I get 0 records returned when the modificationDate > %@ portion is included. I, of course, modify records in the CloudKit Dashboard, and I can see that their modificationDate has updated and is newer than my lastUserFetch date, but they still don't get returned in my search results.

How do I combine a modificationDate comparison with a recordID IN query?

2

There are 2 best solutions below

2
On

Make sure you have queryable index created on modificationDate field on cloudKit

1
On

Use an NSCompoundPredicate:

var predicate:NSPredicate

//Every fetch
predicate = NSPredicate(format: "recordID IN %@", argumentArray: [userRecordIDs])

if let lastChecked = defaults.object(forKey: "lastUserFetch") as? Date{
  //Subsequent fetches
  predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate,  NSPredicate(format: "modificationDate > %@", argumentArray: [lastChecked]))
}
let query = CKQuery(recordType: "User", predicate: predicate)
let operation = CKQueryOperation(query: query)
...