Updating CoreData xcdatamodel file troubles - attribute type change - iphone

I noticed several questions related to this topic go unanswered. Is this such a gray area that nobody really understands it?
Here is my problem:
I am a midway in the development of my app and the app has never been used ouside of my iphone simulator.One of the attributes in my core data structure requires a type change.Since my app has never been used outside of my iPhone Simulator, I first deleted the sqlite file. Doubling the effort of this step, I also went into iPhone Simulator menu and selected "Reset Content and Settings...".
Than, I edited the xcdatamodel file and changed the type of my attribute. I saved the file and exited. Without any other changes, I compiled. I expected it to fail because of my type change. It did not! After this, I assigned a value with new type to my attribute and it fails to compile?!
Is there something else that I need to do for the change to take an effect?
I would really, really appreciate an answer to my question.
Thank you!

Core Data sometimes acts weird until you do Build -> Clean to build from scratch.

When you change the model and there is no sqlite file then Core Data will just create one off of the current model, so your first instance makes perfect sense.
In your second instance, if you did not delete the sqlite file (or reset the sim) between those two iterations you would get an error because the sqlite file already exists from the last run and it no longer matches the model.
Whenever you change the model you need to either version it or delete the sqlite file. Otherwise they will not match and produce an error.
If that is not the issue then it would be very helpful if you gave the details of the error you are seeing.
update
I'd still like to know the right way of dealing with the changes in core data in early development stages when there should not be a need for the migration.
The right way is to delete the application / reset the simulator and start with a fresh sqlite file. There is no other option other than migration and as you surmised, that is incorrect during development.

Related

How to completely reset CoreData for an Xcode project?

My macOS application is a mess right now. I made some big changes to my Core Data model, and now, just launching the app causes the app and Xcode to crash. The app's crash log reveals the following reason for the crash:
Fatal error: Unresolved error Error Domain=NSCocoaErrorDomain Code=134140 "Persistent store migration failed, missing mapping model."
I don't want to create a mapping model. I don't care about the old CoreData model. I want all that data to go away. I have tried the following things:
Deleting Derived Data.
Deleting the ~/Library/Application Support/APP_NAME/ folder.
Using NSBatchDeleteRequest to delete all the entities.
I want to start fresh (without creating a completely new project). What do I need to do to start all over again with a fresh Core Data dataset ?
Search in the Finder for yourAppName.sqlite. I found one in
~/Library/Containers/yourcompany.yourAppName/Data/Library/Application Support/yourAppName/
Well, like #Willeke said, it seems to be as simple as finding the sqlite file and deleting it. That gets you a complete purge/reset without rebuilding the app. Still a pain though if you just want to tweak the structure a bit without losing the accumulated data. So for that scenario, maybe develop an export function first, dump the data, delete the sqlite file, then re-import the data.
Well if you are using the emulator, simply delete all data on it like so:

Core data is lost when reboot iPhone device

I create an application that use two xcdatamodel file to save data. Everything works fine, the data can save and load successfully. But it is weird that when I reboot the device, data in one model is lost and another is still exists. It usually happens on iOS 5.0 and device is locked with passcode.
Is there anybody have this problem too? Please help me about this. Thanks.
Sounds like one or more of your managed object contexts being saved. One way this can happen is if you have a context that's a child of another context. Sending a save message to the child context just adds the modified objects to the parent, but it doesn't get saved to your file. To actually save the data to a file, you have to make sure that you save your root context.

App Crashed due to change in datamodel

My app is crashing when ever i change the data model. Inorder to run it again i should delete the app from simulator and the run it. Instead of doing this is there any means that we can run the app without deleting whenever we change the datamodel. i want the previous data to be used. Thanks in advance
The answer is a bit tricky but this always works for me. This is for a clean installation of a new compatible .sqlite file, not a migration!
launch simulator, delete the app and the data (the popup after you delete the app).
quit simulator
open X-Code, after making any edits to your data model
if needed update the datamodel version:
Editor > Add Model Version...
set your prefs in the dialog that appears (counting up is preferable)
click on the {appname}.xcdatamodeld then in the far right pane
click the left icon of the 3 icons on top of the far right column
under Versioned Core Data Model select the one you just created
delete the {*appname*}.sqlite file (or back it up, remove it from project folder, and delete reference)
clean the app (Product > Clean)
Run the app in a simulator (for this tutorial I will assume 4.2)
While the simulator is running, in a Finder window, navigate to:
{*home*} > Library > Application Support > iPhone Simulator > 4.2 > Applications > {*random identifier*} > Documents > {*appname*}.sqlite
Copy this file to another location
Stop running your app in X-Code
Drag and drop the {appname}.sqlite file into the files list in X-Code.
In the dialog that pops up, make sure the copy to folder checkbox, is checked.
Product > Clean
Then run the app in the simulator again
Now you should have a working sqlite file!
Cheers,
Robert
Basically you need to be able to migrate existing data to the new schema -- read up on Core Data Versioning and Data Migration.
The file being used for NSPersistentStore can only correspond to one version of a Data Model at a time. You need to either do a migration of the data to the new version or tell your application to delete the persistent store file each time you start (for development purposes only).
Just saw that you want to keep your old data. You can try serializing your data to a NSDictionary and then saving it to a plist/json/xml file. Then, when your program starts you can delete the old NSPersistantStore file and create a new one. Import the data from the plist/json/xml file to the new empty persistent store file.
Remember, in order for light migration to work you need to keep the previous version of the data model in addition to the new one. Core data needs to know both models, past and present, in order to perform a migration.
I have the same problem and I haven't fixed it yet. I don't care yet. While my app is in development I just clear the data every time I change the model.
I think to use Lightweight Migration, you still have to make a copy of your data model for every version of the data model you want to migrate from or to. It's lightweight, but not lightweight enough for when you're changing your data model frequently in early development.
I suggest you catch the exception it throws when it can't load the data, and have your program automatically delete the data in that case and recreate it in an initial state. It's the same as the ignore the problem answer but you don't have to manually delete the data every time. You probably ought to leave that code in for production, as a backup in case migration doesn't work for some reason, but maybe you ought to ask the user if they want to delete the data.

Accessing a CoreData entity between app versions, etc

I inherited a project that uses CoreData for a certain type of data storage. I want to remove CoreData from the app and convert the data into a different format...
Over the course of developing other features, I had removed the CoreData framework from the app and the model declarations in such, not expecting to need to convert the old data.
But now I do need to convert the old data. So the first steps I took were to go back into source control, dig out the xcdatamodel files from the old version and plug them back into the app.
Then I went to an older version of the app, installed in on a device, created some data...
Then when I go back to the newer version of the app with CoreData "re-installed", I get a crash claiming that the data entity in question cannot be found in the managed object context. I triple checked spelling and syntax and it checks out.
I feel like maybe I'm missing some vital piece of configuration to make it recognize the xcdatamodel file that declare the entity.
Any insight would be helpful.
What the core data schema versioned? Are you sure you have the right version? One thing you could try if all else fails is just to open the sqlite database file that core data uses for it's backing store and write your own migration routine.
Did you add new entity after 'that' old version? If yes then you need to write migration code for new version.
I made a syntactical flaw that was causing the full context to not be loaded properly... when I changed that then everything loaded fine.
Sometimes these frameworks give the most misleading errors...

sqlite DB to-do during iphone app update

I have some general questions about iphone app updates that involves sqlite db.
With the new update does the existing sqlite db get overwritten with a copy of the new one?
If the update doesn't involve any schema changes then the user should be able to reuse the existing database with their saved data, right? (if the existing database doesn't get overwritten from 1 above )
If there are some schema changes, what's the best way to transfer data from the old database into the new one? Can some one please give me guidelines and sample code?
Only files inside the app bundle are replaced. If the database file is in your app's Documents directory, it will not be replaced. (Note that if you change files inside your app bundle, the code signature will no longer be valid, and the app will not launch. So unless you are using a read-only database, it would have to be in the Documents directory.)
Yes.
What's best depends on the data. You're not going to find sample code for such a generic question. First, you need to detect that your app is running with an old DB version. Then you need to upgrade it.
To check versions:
You could use a different file name for the new schema. If Version2.db does not exist but Version1.db does, do an upgrade.
You could embed a schema version in your database. I have a table called metadata with a name and value column. I use that to store some general values, including a dataversion number. I check that number when I open the database, and if it is less than the current version, I do an upgrade.
Instead of creating a table, you could also use sqlite's built-in user_version pragma to check and store a version number.
You could check the table structure directly: look for the existence of a column or table.
To upgrade:
You could upgrade in place by using a series of SQL commands. You could even store a SQL file inside your app bundle as a resource and simply pass it along to sqlite3_exec to do all the work. (Do this inside a transaction, in case there is a problem!)
You could upgrade by copying data from one database file to a new one.
If your upgrade may run a long time (more than one second), you should display an upgrading screen, to explain to the user what is going on.
1) The database file isn't stored as part of the app bundle so no, it won't get automatically overwritten.
2) Yes - all their data will be saved. In fact, the database won't get touched at all by the update.
3) This is the tricky one - read this fantastically interesting document - especially the part on lightweight migration - if your schema changes are small and follow a certain set of rules, they will happen automatically and the user won't notice. however, if ther are major changes to the schema you will have to write your own migration code (that's in that links as well)
I've always managed to get away with running lightweight migrations myself - it's by far easier than doing it yourself.
What I do is that I create a working copy of the database in the Documents directory. The main copy comes with the bundle. When I update the app I then have the option to make a new copy over the working copy, or leave it.