CloudKit Reference and Index Issues
CloudKit also automatically creates indexes for each field in each record type - when you’re done with development, you can delete some indexes that you won’t need so they don’t waste space in the production database.
A request to fetch records performs a query on indexed fields for a particular record type. At least one field in the record needs to be indexed to perform an empty query that fetches all records. Because indexes are updated asynchronously, they are not guaranteed to be current.
The solution is to use
CKFetchRecordChangesOperation
, if the data is in a custom zone of the private database. If you are using the public database, or the default zone of the private database, think about this:
- The device making the changes knows the changes. [meaning: keep a cache of the updates you make]
- The other peer devices observe the changes using CKQuerySubscription.
This is one of those posts, exploring how querying based on CKReference works, and what are the limits and behaviors of that.
[…]
Here is one important bit: you can’t do queries by
parent
property. I couldn’t immediately find the authoritative source for this in the SDK documentation, but the recommendation in Apple forums and elsewhere has always been to add your ownCKReference
fields if you want to query by parent record.[…]
The key bit is the predicate for the reference set. I got the idea for setting up this way from this StackOverflow post. The official CloudKit documentation does have examples for querying based on references, but not reference sets and more complex scenarios.
[…]
Fair enough. This tells me that the filtering condition in the clause
ANY %@ in relatedRecords
can’t contain more than 250 objects. So, let’s limit it, leave some headroom, and run it with 200 records instead.[…]
Even though the input contains only 200 objects, I get this error. I speculate that even though the input amount is below the nominal stated limit, some relationship query to construct the results causes some internal limit overflow on the CloudKit side, and it doesn’t handle this situation well.
Thinking about this some more, and in chatting with the good samaritans on Slack, we all came to the same conclusion: the index probably didn’t properly… uh… index… whatever data was already there before the index was created.
So, if you’re ever in a situation where you’re getting wonky results (or no results at all) from a new field in CloudKit, consider whether the data you’ve added was done so before or after you added the corresponding index.
Previously: