Adding entities/attributes to CoreData in a live app - ios

I have finally published my first App, and am now looking to make improvements from user feedback.
The app uses CoreData with existing schema entities and attributes. I am looking to add additional attributes to existing entities, and add some new entities.
My question is, can I simply make changes to the CoreData schema then publish the app's update? Is there any migration process I need to be aware of? What do I need to consider as the impact on existing app users?
I vaguely recall reading many months ago that I should "version control" CoreData? Though I might be completely wrong.

Look into lightweight migration and model versioning, also test, test and test.
https://developer.apple.com/documentation/coredata/using_lightweight_migration
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/Introduction.html
This is also a really good article
https://www.grantgrueninger.com/2020/01/nspersistentcloudkitcontainer-in-production/
I emphasize sending an update with just the core data changes before the code that actually uses the changes to prevent inconsistencies when the user has 2 devices.

Related

How the Core Data Migration will work for two projects?

I'm working on an app which using core data (one app is already live on the AppStore). OK, now I want to make it fully functional for iOS8 and client also asked me to make a good change in UI and its structure so I started a complete new project and decided to code it my self. Everything works fine, then client emailed me and confirm that, new version of app should store & fetch existing values from the database if existing app will get update. I feel bad here.
I know core data migration is possible ( I read this too, but there's some glitches in my mind about this concept.
As I told, I started a new project though is it possible to add a new version of the model?
Our entities and attributes names are not same. I named it the way I want.
Our model name is same. e.g. Somename.xcdatamodel
My app will update to the existing app on the AppStore.
How I can migrate the existing core data database to the new one?
Is this possible? How?
Any suggestions and help on this would be appreciated.
Note:
I read this question, Core Data Migration: How to delete the Core Data stack? and found that there's no issue if I delete the previous model? What you suggest?
If you need to migrate and keep the existing data, you should read more about writing custom policy Core Data Versioning Guide. Read this guide completely to get to know which category your app migration falls in.
1. Lightweight migration.
2. Or you have to write your own custom policy.
As far as i can tell from the details you provided it looks like it might be a lightweight migration for which you do not have to do anything you can just add a new version to xcdatamodel and mapping models. If not then you have to write your own custom policy and mapping models.
Also make sure you test upgrade properly.

iOS CoreData Migration using Custom Mapping Models with multiple historical database versions

I have an app and many history versions of the database.
Our users are typically "once in a year" users, so this means you can never be sure which version of the database their app is running on.
Now in my new version of the database I need to do some custom migration.
The method I use to do this is described in this tutorial: http://9elements.com/io/index.php/customizing-core-data-migrations/
To summarize: I have to make Custom Mapping Models so that I can write my own migration policies for some fields.
Now when I create a Custom Mapping Model, I have to select a Source "xcdatamodel" and a Destination "xcdatamodel" (where "destination" is te new version of my database).
My question is, if I want to do this custom migration from all possible versions, do I need to create multiple Custom Mapping Models, all with a different source, or is there a smarter way to do this?
Or is CoreData smart enough to recognize this?
The short answer is yes; you need to test every migration from every source model to your current destination model. If that migration requires a custom mapping then you will need to have a mapping for that pair.
Core Data does not understand versions; it only understands source and destination. If there is not a way to get from A to B then it will fail. If it can migrate from A to B automatically and you have the option turned on, then it will. Otherwise a heavy (manual) migration is required.
Keep in mind that heavy migrations are VERY labor intensive and I strictly recommend avoiding them. I have found it is far more efficient to export (for example to JSON) and import the data back in then it is to do a heavy migration.
It is enough to have a consistent sequential series of migration models up to the current version. Core Data is "smart" enough to execute the migrations you tell it to migrate in the given order.

Modifying the Core Data Model Requires New Version Every Time?

I've been searching around and let me get this straight, every time I change the attributes of my entities, I need to create an entirely new version of my model? I understand that the SQLite database is now out of sync with my data model, but can't I just delete the sql files and re-run my simulator? This is what I've been doing, but it doesn't seem to be working.
You are correct, any changes to the core data model must be made in a new core data model version. You can avoid having to do this for development builds by resetting content and settings in the simulator, or deleting the old app version on a device before installing. For store builds though, you must correctly manage your model versions so that user's will have their persistent store properly migrated to a new store with the new model. Versioning is required so that lightweight migrations can be performed, without you having to write custom migration code. If you don't want to version your model, you are bound to writing code to properly migrate your entities. This can be a lot of work and difficult to maintain, you'd rather use lightweight migration and versioning.

change attribute value in Core Data in already published application

(Actually, I don't know how to formulate my question, so in google I found nothing.)
So, the situation: In app in appstore I've the Core Data entity (let's say Weather), one of its attributes is Speed type String. Now it contains single line (e.g. 5 mps), but now I want it to contain an array-like string (e.g. 5 mps; 6.4 mps; ...) also change name from "Speed" to "SpeedHistory".
And I made a new model verison, chose it (it has little checkbox now), renamed the attribute, set "Renaming ID":"Speed" and now: how should I act, to prevent user's of old version data crash?
Could you give me some advice, please?
P.S. Data in Weather Entity is fulfilled by user. And I'm using MagicalRecord.
This is a rather common issue. When you update your model when using core data you have to migrate it. You can follow this tutorial which explains what you should do to fix your issue:
http://www.raywenderlich.com/27657
A lightweight migration is also relatively simple and can be performed safely. You only need to worry when the changes in your model kind of require a change in logic.
Changing the type of a column is something that can't be done with lightweight migrations. If you want to migrate the users' data when they upgrade to your new model version, you'll need to create a mapping model. This process is described in the Mapping Overview section of Apple's Core Data Model Versioning and Data Migration Programming Guide.
I haven't had much success with mapping models, as they seem to be very memory-hungry.
Have you considered adding the SpeedHistory attribute without removing the Speed attribute or setting a renaming identifier? Then in your model class you could override awakeFromFetch:, check whether there's a Speed, and if there is then set the SpeedHistory as appropriate and clear the Speed. You'll migrate the objects one at a time, on an as-needed basis.

Is it possible to add a new attribute to Core Data without having issues with users and their current data?

I want to add a new attribute to my Core Data model but I'm worried if I do the users data will no longer work, and they'll have to redownload the app. I've had issues before where I change it a bit (though through deletion) and it causes big issues with the app where I need to reinstall it.
How should I go about doing this?
The process is called Core Data Migration: Ray Wenderlich has a great tutorial on it here. If you are just adding a new attribute, it should be (relatively) simple to do an automatic/lightweight migration.

Resources