Making Changes to Data Model with SQLite iOS - ios

I'm reading data from a pre-populated sqlite database using CoreData. Everything is fine and dandy, except when I decide that I want to add another entity to the CoreData model (and another table to the sqlite database). I've tried several things, including making the changes to the model in Xcode, removing the sqlite database, and then hoping it generates a new database like it has in the past.
However no matter what I've tried, I get this error:
The model used to open the store is incompatible with the one used to
create the store.
Maybe I'm not doing this the right way, but it seems like Xcode makes it difficult to change the data model, which doesn't make sense to me when you're developing an app.

In general, if you delete your app and recreate it, the boilerplate code that comes with the project will generate you a new (and like you say, compatible) database.
Also, CoreData is intended to be used as an object graph with persistence; what it does with the generated SQLite DB as a result of providing this is its own business.
If what you're saying is: 'I have a valid CoreData store file and model, and I'm trying to hand-upgrade the store file to match a new model', you're breaking the rules of the framework. To morph an incompatible store to a new model, you need to use versioning and mapping models (without directly touching the SQLite DB).

Related

Using CoreData along with a bundled SQLite database?

I’m new to the iOS dev party so now I’m struggling with some issues. I want to create an app that uses a database for returning some information to the user. For this I added a SQLite database into the project and used this (https://github.com/stephencelis/SQLite.swift).
Now I want to add a new feature to the application that will let the user add some bookmarks in order to save some pieces of that information. For this, I need to update the database which is causing me some major concerns: how can I update the app without overwriting the user’s bookmarks? What happens if the user skipped two updates prior to the 3rd one? As you can see, this can turn into a huge pain.
So I was thinking on using this bundled SQLite database only as a readonly db and along with it to use CoreData for storing the user’s bookmarks. What do you think? Is this the right way to go?
Core data as you know is a persistant data that will be with your application. Well i still cant understand what seems to be the problem with maintaining the SQLite database but if this is a problem then i dont think core data will solve it. Having core data along with the SQLite database with you explicitly not chaning the DB and just "remembering" bookmarks in core data and fetching them from SQLite might do the trick. This is a conceptual problem that you are facing.
CoreData is a great framework, but it is not trivial and it add complexity that maybe is not required from your project.
If the bookmarks are not a lot of data you could store them in the NSUserDefaults.
this example can be useful :
(http://ios-blog.co.uk/tutorials/quick-tips/storing-data-with-nsuserdefaults/)

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.

Resources