I am trying to master Code Data migration, its going to be important for supporting my app. The reason I need the migration is to preserve data. My app is used for psychological research and collection reaction time data. I have a game session and every game session has ordered set of moves. Every move has some properties. One of this properties is interval: Date. In the store version 1 it was named date and in the version 2 I renamed it to the interval and changed property's model version identifier to date.
App is not crashing on startup but when I am trying to view my old logs it crashes. I have UITextView and I display all my logs like this:
textView.text = "Interval = \(move.interval)"
If I create new game session and will view its log - the app works.
What is the best way to protect my users? Should I add additional logic inside my app for this? How can I display the old data after property was renamed?
Update:
There's no messages in the console, the app stops working with the line of code for updating the UITextView, it is highlighted in green with error message:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
I tried again from scratch and instead of renaming the variable, I created new one. This time app didn't crashed. I am sorry it is not real answer but it helped me to move on.
Lessons I learned:
Do not confuse Core Data Model Identifier in Xcode inspector and renaming ID. There's one model identifier (I left it empty) and renaming ID for every property.
If you have Core Data generated class with NSNumber, do not try to display them in console like this: label.text = "number = \(object.number)"
Do it like this:
label.text = "number = \(object.number.integerValue)"
This one gave me the same crash message, however it is not a problem if you're using NSDate.
I still have a problem when renaming variable. When I applied my commit again today I am getting the crash right on the start with the Can't find model for source store message. App in the simulator changed, so it looks like I can't reproduce this problem any more and instead have a new one.
Update
I had more practice and I think I was able to fix the crash described above.
I added next data model version - version 3 and introduced new variable. I did it like before, with switching current version from 2 to 3. Then app started to crash on launch with Can't find model for source store. I noticed that when I'm removing introduced variable the app is not crashing. I figure out that my Core Data couldn't migrate to version 3 because it already was on version 3:
I changed version from 2 to 3. I didn't change Core Data model.
I changed my code, fixed some bugs unrelated to Core Data.
Built and ran the project in the simulator. Note, now the app in the simulator has data version 3.
Changed Core Data model, built on simulator. It crashed after this step.
What I did to fix this:
Delete introduced variable. You can live generated classes as it is.
Change current version to previous. In my case, from 2 to 3.
Run the app and quit it.
Change Core Data current version and add new variable.
Run the app — it works.
Update 2
I met with this problem again and my answer didn't helped. Still, event after everything I described above.
I found this answer which this time finally fixed the issue. The secret was that new attributes should not be optional and they should have default values.
Related
Background/issue: I have a Core Data app in production and I just sent out an update where I added a couple of attributes in an existing entity without making a new model version (I didn't know this was a step). This is causing my user's apps to crash. The crash only happens when they first open the app after updating then it seems to work fine after the initial crash.
How I think it can be fixed: I'm thinking that I should go to a previous commit > copy the old data model > go back to master > delete the updated data model > drag and drop the copy into Xcode > then go to Editor to "Add Model Version". After add the new attributes I need I'm scared to do this and submit it to the App Store as it may cause more problems for people who already updated their app.
Ask: Is there a way I can revert my changes to the old data model version then make a new one from that? Without affecting my current users who already upgraded to the database version with errors?
I paused the phased release of this update to stop having users get crashes so if anyone knows how to fix this please help!
I am working on a iOS mobile application using Xcode as the IDE and Swift as the language of choice. I added a column to the SQLite database that interacts with my application but unfortunately when I attempt to perform any database operations through the application the column is not recognized.
The following error is sent:
DB Error: 1 "table xyz has no column named column_name"
When I added the column I also increased the database version or user_version in SQLiteStudio.
Is there something else I should be doing to cause the application to recognize the changes? I know uninstalling and reinstalling would work but that is not an option of course as I cannot lose the data currently housed in the database. My other idea was to put all the data in temporary variables or something like that, drop and recreate the tables and reinsert the data. I wasn't sure if this was a good course of action though. Any help with this is appreciated.
In our existing app, we have many different version of xcdatamodel:
+ TheApp.xcdatamodel
TheApp.1.0.xcdatamodel
TheApp.1.1.xcdatamodel
TheApp.2.0.xcdatamodel
...
We know that the traditional way of doing database migration testing is what have been proposed in this question: How to Test Core Data Migration With an App Already in the App Store? In short, it works like the following:
install a old version of the app;
create some data in the old version of the app;
install the new version on top it;
see if everything is migrated properly.
We have been using this migration testing method for all our previous version of the app. Our QAs will perform the above steps and then judge by themselves that whether migration is successful or not.
However, in the most recent upgrade, we have changed a lot in our data model. It doesn't sound like such a good idea to ask the QAs to remember what have been created in the old version of the app and know what have been missing or not during migration. Therefore, we would like to see whether it is possible to write unit testing for the database migration by the developers ourself.
So one of the first step is to generate test data. Notice that we can see all the previous version of the xcdatamodel from within our Xcode project, it seems that it is possible. In a nutshell, the question:
Is it possible to generate test data of previous version of xcdatamodel programmatically from within our current version of the app?
Please let me know what you think. Suggestions are also acceptable.
This is how we do it: we need to first get an URL to any model you would like to work with, and then create a managedObjectModel from it.
let oldModelUrl = NSBundle.mainBundle().URLForResource("CoreDataExample.momd/CoreDataExample",
withExtension: "mom")!
let oldManagedObjectModel = NSManagedObjectModel.init(contentsOfURL: oldModelUrl)
Referece: https://medium.com/#yzhong.cs/1d9f941b3168.
My CoreData Worked before when I had an entity with one attribute called test, I tried to add a new attribute in the data model and I also defined it in my data.swift file but when I launch the application, it crashes on the loading screen every time, what am I not doing right? I can provide my code as needed.
When you run the application and then change the CoreDataModel, the next time you run the application it will give you an error indicating that the data model used has changed. To fix this, you can either remove the old version from the simulator (or device) and run the app again, or you can create a new CoreData version.
If just testing before the app has been released, deleting and running the app again works fine...
At the early stages of development, where data retention is no issue and experimental changes to the schema are expected to be numerous, is there a way to avoid migration? Namely, just to dump the database and start over each time.
Everything I try leads to the error: "The model used to open the store is incompatible with the one used to create the store".
Lightweight migration looks do-able, but I'll end up lots of unwanted versions and messy code. I'd also like to experiment with relationships (no wise cracks), but understand I'd need to commit to a heavyweight migration afterwards!
If the solution is to check for the existence of the original database using NSFileManager and delete/remove it if found, could someone please show the swift code with an example name of the original database, and how it can be effectively removed.
I've been trying several suggested solutions, such as dragging a copy of the .xcdatamodeld file onto the desktop, deleting the file in xcode and bringing it back in, but I keep getting the error that the model and store are not the same.
Answered in one line in first comment, but appreciated in reverse proportion.