I think have worked out what’s going on as I was having the same problem, despite following all the steps in Apple’s Documentation for NSPersistentCloudKitContainer
.
To make sure your Core Data entities are all created correctly in the Development Environment, before deploying to the Production Environment, they recommend running (once) the .shouldInitializeSchema
on your NSPersistentCloudKitContainer
.
Problem is, this hasn’t been valid for months (see more below...) so the other way to do it - and the way I did it - was to create all my data on-the-fly, saving to Core Data which created the schema in the Development Environment via NSPersistentCloudKitContainer
. I then deployed it to Production when it was working perfectly on my devices.
While it was working perfectly well for my data, it wasn’t working for any of my users in the real world using my App Store version of the App. It was a real head-scratcher.
It turns out that there were a few missing Custom Fields in one or two Custom Types in the CloudKit Schema for my Core Data model - attributes which exist in my model but which I no longer use (one was just an empty string which I never use).
Problem is, NSPersistentCloudKitContainer
doesn’t like this, even if an NSManagedObject
has attributes you don’t use, they must be present in the CloudKit Schema for it to work. It seems to need a Custom Field to match each attribute in the Core Data model exactly.
Why it worked on my devices might be related to the fact that at some point in the past, these Custom Types and Custom Fields were all present in the Development Environment prior to a reset, by which stage my devices had everything in place already for them in iCloud.
The Custom Types (as seen in your CloudKit Dashboard) need to have Custom Fields that match every Core Data Attribute for the corresponding Entity as well as a Custom Field for each ‘to-one’ relationship (I had one of those missing too). They are all the fields that start with CD_
which are autogenerated by NSPersistentCloudKitContainer
.
The ‘to-many’ relationships seemed to be stored elsewhere.
With Apple’s help, they suggested running the .shouldInitializeSchema
replacement initializeCloudKitSchema(options:)
(not yet in their documentation!) on the container (just once) to fill in all the gaps.
When I did this, I noticed it didn’t actually add any missing Custom Fields at all, and when I ‘Deployed to Production’ there were no changes to make and while it still worked on my devices, production devices weren’t working. On further analysis, the missing fields were NOT added...
So, instead, I made sure some data was written to my test device for all these missing attributes & ‘to-one’ relationships, then tried again.
I could see they were all now present in the Development Schema, which I deployed to production. All the missing Custom Types and Custom Fields were listed in the change.
It now all works for my users!
What a complicated process. Partly my fault, partly Apple’s.