Unreleased xcdatamodel versions and lightweight migration - ios

If I have multiple unreleased xcdatamodel versions between release A and release B, will lightweight migration still work once I release to the public if I delete the unreleased versions?
Here's a more discrete example:
xcdatamodel version 1.0 --> Release to public A
xcdatamodel version 1.1 --> unreleased (based on v1.0)
xcdatamodel version 1.2 --> unreleased (based on v1.1)
xcdatamodel version 1.3 --> Release to public B (based on v1.2)
I want to make sure that when I submit release B, users coming from release A will be migrated properly. Or is this a completely terrible way to go about it? I understand that if I didn't care about the data on my testing devices, I would just base xcdatamodel version 1.3 on version 1.0 and put everything new in that version - I just don't want to lose the data on my testing devices that have had versions of the app with v1.1 and v1.2 already on the device.
Thanks!

Assuming that the format used for existing user data can be converted to the current format via automatic lightweight migration, it doesn't matter that you created internal, unreleased versions.
What you need to include in the released app: every version that any user might be using. In your case it looks like people would only have 1.0-formatted stores, so there's no need to include 1.1 or 1.2. If that's not the case-- i.e. if there's a user out there somewhere who might have version 1.1 or 1.2 data-- then you need to include them.
So, as long as the 1.0 --> 1.3 changes work with automatic lightweight migration and that no users have 1.1 or 1.2 format data, you could just delete the intermediate versions.

Lightweight migration will only work with certain types of model changes. The best thing is to test this thoroughly. You can safely do the following:
Add new optional attributes or relationships to an entity
Add new required attributes to an entity with a default value
Change an existing optional attribute to required but with a default value
Rename an attribute or relationship or entity and specify the old name in the "Renaming ID" field of the core data utilities pane tab.
The Core Data Model Versioning and Data Migration Programming Guide lists more operations, but again you should test all this.

Related

CoreData migrations without versioning

Right now I use versioning to make any changes in a database. But it brings some problems. For example it's hard to merge a feature branch with a new db version into a master/dev where somebody also added a new version.
So my question:
Is it safe to change db in a single xcdatamodel without adding new versions? I tried so and it works but everywhere on the internet I see warnings that you must not do that.
iOS9+.
I found this: https://stackoverflow.com/a/37264096/5328417 but it's without a proof
As #pbasdf noted, since iOS 9 you can do a lightweight migration without adding any new model version. Source model (previous model version) is cached to store and used as a last ditch effort during lightweight migration.
I am using this feature in my own apps successfully. Although I was not able to find this documented. Just that WWDC video (18'15 Model Caching) mentioned. This is exactly the reason why Core Data is so mysterious sometimes..
If your app is in development stage then you may use one model without versioning.
But if it is release on the App Store then you have to create the versions when you make changes (such as adding a new attribute, adding a new entity, renames attributes etc.). Otherwise, Core Data won't perform lightweight migration.

How to manage versions of Data Model Schema versions

I am having an app on app store. I have to update model version after every 2 months on average due to updates.
I have 7 versions right now and they will definitely increase in future.
I have some questions:
How I can efficiently manage this
Can I delete my older version?
How many versions I can add?
How I can efficiently manage this
I recommend naming the model versions based on the release they are associated with. It helps to keep things straight.
Can I delete my older version?
Yes but not recommended. If someone is still using an older version of your app they will fail to migrate if the source is not there.
How many versions I can add?
Unlimited. However you should only have a version for each production release where data structure has changed. If you have intermediate versions that only exist for development, I would recommend removing them as they don't impact the user.
Lastly, make sure you have a unit test that migrates from every old version to the current version. Core Data is not temporal and will not go from 1 to 2 to 3. It only understands source and destination. Can your app currently migrate from 1 to 10? If not, you need to address that.
How I can efficiently manage this
Continue to increase versions when you add changes to model.
Can I delete my older version?
Yes you can. Just open data model in finder and delete version, re-add data model to project. Also make sure you handle NSPersistentStore creation fail (if merge is unsuccessful).
How many versions I can add?
As many as you need.

Confused by how to setup my .xcdatamodel for versioning

I am reading the Core Data Model Verisoning and Data Migration Programming Guide and am confused on how to set up the initial verison number.
I have an existing app in which I did not set it up for Core Data versioning. In addition, I am using Magical Record. The current version of the app is 1.3; I am ready to release 1.4 with some minor changes, and I want to change one of the Core Data entities (add new attributes) in release 1.5. I absolutely need versioning so my users will not lose any existing data. I assume I must set up the current verison to enable Lightweight Versioning for release 1.5.
The question is: does the Core Data version have to match the app version? or is that the common way for versioning to work?
Magical record has a convenience method for this. In your AppDelegate where you setup magical record use.
[MagicalRecord setupCoreDataStackWithAutoMigratingSqliteStoreNamed:#"storeName"];
Alternatively click on your core data .xcdatamodeld then top bar Editor > Add Model Version

Core Data Lightweight Migration - when to version?

Can I do the following?
Start with v1.0 of an app. Version data model, designate new version as active schema
Set correct options in appDelegate for creating NSPersistentStoreCoordinator using lightweight migration
Make simple changes to the model and update classes. Compile and verify that everything works.
Make another change to the data model without changing the version, and again update the classes
Of course when I run, the data model will be incompatible since I have changed it without versioning. But since I will not be shipping the intermediate version, my suspicion is that the data migration should work fine when updating from v1.0 to the double-updated data model.
Is this accurate?
It will work as long as the following are true:
You have created a new model version for each of these steps; so in your example above you should have three at the end: original, intermediate, final.
The app must be able to do a lightweight migration from 1 to 3. If it cannot it will not go through 2 if the data on disk is still in the structure of 1.
If all of that is true then it will work. And you can even go so far as to not ship v2 in the final build (although they are small and it is usually not worth the effort).
During development my recommendation is to always keep the v1 data around, only change v2 and remigrate every time you need to adjust v2. Then there is no intermediate to deal with. However that is not always possible when dealing/working with beta testers.

Combining or skipping version of the core data model

During development of a new feature, I have versioned my core data model a few times, always using lightweight migration. I am working on v1.5 of my app and now have versions 1.5.0, 1.5.1, 1.5.1, etc of my core data model. Only the final version is going to be used by a deployed product - to put it another way, had I been better able to predict the model I would end up with, my v1.5.0 would have looked like v1.5.99.
Is there some way to consolidate the intermediate versions, so that the migration is one-step? If I don't do this, will the migration run multiple times, and will there be a performance impact?
I am considering restoring my v1.4 version and manually re-creating the final model version as the only new version, but am not looking forward to re-adding all of the other code that has been updated in the same branch.
If (1) you don't have any data stored with the 1.5.0, 1.5.1, etc. versions, and (2) migration from 1.4 to 1.5.99 can happen automatically, then you can just remove the intervening versions from your data model.

Resources