swiftcore-datacloudkit

How to update the CloudKit schema after the app has been released to the AppStore


I recently had an issue with one of my production apps that use Core Data and CloudKit where data wasn't syncing between devices, after a little bit of research I found out that the schema in the private CloudKit container needed to be initialized; which I never did.

The part I'm still not 100% sure is when to run the initializeCloudKitSchema method after the app has been released to the AppStore. I see that Apple recommends running it when testing by using #if DEBUG, but... do you really want to run it every time you compile in Xcode?

Here is how I understand it at this point...

  1. App release, call initializeCloudKitSchema() to match schemas between Core Data and CloudKit.
  2. Added or deleted and attribute, call initializeCloudKitSchema() to update the CloudKit schema.
  3. Renamed an attribute, call initializeCloudKitSchema() to update the CloudKit schema. Etc.

If my assumption above is correct, calling the initializeCloudKitSchema() method during development would update the schema in CloudKit before the new app version is released in the AppStore, therefore creating an issue for existing users with previous versions of the app since they will not have the latest code but will be using the latest schema which contains the new attributes.

Can someone please share their method of handling schema updates in CloudKit after the app has been released to the AppStore?

Code:

do {
    try container.initializeCloudKitSchema()
} catch {
    print(error)
}

Solution

  • In my case, I didn't even need to run the initializeCloudKitSchema() method. Here is what I did that worked for me.

    1. I tested locally with two devices and made sure everything was syncing as expected. This of course was done in Xcode within the sandbox environment using testing login accounts.

    2. Then I went to the development CloudKit container and clicked on the Deploy Schema Changes.

    3. Lastly I went and downloaded the app directly from the App Store on two different devices using a production/regular user account and tested it. Everything worked as expected.

    4. Done

    In theory, it looks like you need to deploy the schema to the Production CloudKit container once you're satisfied with the schema and the results in the testing environments by doing the above or possibly calling the initializeCloudKitSchema() which I didn't try.

    Side notes: It looks like once you deploy your schema to the Production CloudKit container you no longer can delete or rename Entities or Attributes. Also, you will have to do the above every time you update the Core Data schema. Keep in mind that if you add or remove Entities or Attributes in Core Data, you must create a new version of the Core Data container to do what is called a light migration.

    EDIT: Here is how to create a new version of the Core Data container.

    1. Open Xcode and select the Core Data container.
    2. Go to Editor > Add Model Version.
    3. Enter a name for the new version. I use the following naming convention, CoreDataContainer-v2. I basically add -vX to every new version.
    4. Open the File Inspector on the right and set the "Model Version" drop-down menu to the new model version, CoreDataContainer-v2.
    5. Go and expand the CoreDataContainer; please note that now it should have two containers underneath, the original and the new version. Make sure the new version is selected.
    6. Add your new entities or attributes.
    7. Test and make sure there are no errors.
    8. Go to CloudKit and Deploy Schema Changes.
    9. Done.