I've recently released an app that uses NSPersistentCloudKitContainer
. In development my database is synchronizing across devices as expected, but in production my database is not synchronizing at all. Once I debugged the situation, I realized I had to publish the iCloud Schema to production. But even after doing that, my app is not synchronizing across devices in production.
Has anyone experienced this? Is there something else I need to do for NSPersistentCloudKitContainer
to work in production?
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.
I had the same problem, in my case the problem was that I was only activating the capabilities in the "Debug" section, because it is the tab opened by default when selecting "Signing & Capabilities"
Double check that you are also activating the needed capabilities in the "Release" section.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With