The Statement
I have a SwiftUI
app that uses CoreData
and iCloud
with NSPersistentCloudKitContainer
prepared for beta testing via TestFlight.
The app utilizes iCloud solely as a private database for user data across different devices. The app doesn't use any public or shared database.
According to Apple's guidelines, deploying the development schema to production is necessary before submitting to the App Store:
Before you publish your app, you must deploy the development schema to the production environment to copy over its record types, fields, and indexes.
I am aware that once deployed to production, it's impossible to delete or modify any types or fields:
To prevent conflicts, you can’t delete record types or fields that are already in production. Every time you deploy the development schema, its additive changes merge into the production schema.
The Questions:
- When is the appropriate time to deploy the schema to production?
- Should it be done before beta testing via TestFlight, or is it sufficient to deploy it just before releasing the app on the App Store after beta testing?
- If the schema needs to be deployed before beta testing, does that mean I won't be able to reset the schema if testers discover critical bugs related to the data model, and I'll be compelled to delete or modify any types or fields?
Thank you in advance for any responses!
hi,
my suggested answers are:
(1) appropriate time to deploy? see (2).
(2) Should it be done before beta testing via TestFlight? yes, you must move to production before users can test via TestFlight.
(3) does that mean I won't be able to reset the schema if testers discover critical bugs related to the data model? well, this one's more nuanced.
as you know, once you are in production, that CloudKit schema only allows additive changes (add an attribute to an existing entity, or add a new entity).
if there are problems in the database schema, there's no reason you cannot make any necessary additive changes, and then simply ignore values of entities and attributes that are no longer needed. for example, if you want to change a relationship from one-to-one to one-to-many, add a new relationship between the two entities; read the existing one-to-one relationship's value; and set the new one-to-many relationship.
if you really want to keep the CloudKit container trimmed, you could take the time to remove all objects of a given entity type (the entity type would still be in the CloudKit schema; there just would be no objects of that type), and you could set attributes no longer in use in a given entity to some small space-consuming value (e.g., "" for a String, or nil for a Data). nullify any relationships no longer in use.
i would suggest that you consider an explicit version number attribute to all the entities in your schema, with default value 1 (or whatever is your current core data model version). if you do make (additive) changes in the future, you can update the version number; and you can later test this in code to know what record type you're working with and what fields it has by first checking its version number, and then use appropriate logic to work with the object.
the best reference on this might be to start with David Stites's WWDC2022 video named "Evolve Your Core Data Schema". the last third of this covers the CloudKit issues.
finally, if you really do want to reconfigure the data model once it's in production, could you possibly define the new version of your core data model, which takes care of the local data store ... but then assign a new CloudKit container to your app? i don't know the answer to this one, but perhaps you won't need go there.
hope that helps,
DMG