I didn't migrate NSPersistentStore in new version, can I recover with an app update?
Asked Answered
L

1

12

long story short, my Core Data schema was changed, and my app was submitted to the app store, which caused everybody who updated their app to crash. The crash is caused by a missing NSPersistentStore due to not migrating the data model properly.

I still see the .sqlite and associated database files in the documents directory, and if I downgrade to the older version everything works fine with all data. My question is, can I recover from this with an app update by somehow migrating the existing NSPersistentStore and adding it to the NSPersistentStoreCoordinator?

EDIT: so I didn't actually change my xcdatamodel myself, hence, "long story short". However, I did remove XMPPFramework from my project and I have a feeling this might have caused the core data problem.

EDIT:
I didn't make any changes directly to my data model, but I have pinpointed the problem. I was retrieving my NSManagedObjectModel using [NSManagedObjectModel mergedModelFromBundles:nil] which merges ALL data models present in the bundle. This included all data models that came with the XMPPFramework, and now that the framework has been removed, the NSManagedObjectModel that is passed into [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel] is different, thus causing the crash.

I resolved the problem by using FMDB to fetch the contents of the existing DB, then created a new sqlite file and pointed the persistent store coordinator to that new sqlite file. Then I just inserted all the existing data into the new database by looping through the existing data and creating the appropriate NSManagedObjects. I also stopped using mergedModelFromBundles to retrieve my data model and instead use initWithContentsOfURL.

Lownecked answered 23/7, 2015 at 15:29 Comment(10)
If you didn't change the model, what leads you to conclude that the crash is caused by not migrating data? Migration isn't necessary unless the model has changed.Personification
The error has to do with a "missing persistent store" in my NSManagedObjectModel. This is always (?) due to a change in the data model. There is some messy code in my app that edits some NSManagedObject properties in the code so the entire schema is not defined in the xcdatamodel, which may be causing a problem as well.Lownecked
I guess the problem is that it's hard to understand what has actually changed. You seem to be saying that the model changed but also that it didn't change. What exactly happened with the model?Personification
CoreData: error: Illegal attempt to save to a file that was never opened. "This NSPersistentStoreCoordinator has no persistent stores (schema mismatch or migration failure). It cannot perform a save operation.". So I did not change my .xcdatamodel at all, which is the weird part about this error. BUT, there may be some code that dynamically changes the data model on the fly but I didn't write that code so it's impossible to know. Is that even possible though? To change the data model without changing the .xcdatamodel file?Lownecked
Yes, models can be changed in code. You can recover from this situation, but only if you have a very clear picture of how and why the model has changed in the new version. If it's impossible to know, then it's impossible to fix.Personification
Hm, yeah that may be what happened. My other guess is that removed the XMPPFramework from my project (using cocoapods) also removed a bunch of .xcdatamodel files from the project. However, I didn't actually use XMPPFramework anywhere before removing it, and the .sqlite database that is causing the crash is my own app's DB, not XMPPFramework's...Lownecked
"My other guess is that [...] also removed a bunch of .xcdatamodel files from the project". The first thing you need to do is stop guessing and work out exactly what the changes are, because those details are critical to any recovery strategy.Personification
The 1st thing your App Update should do is copy the old DB file to a new location, as to back it up on the user's device. Then you create a new one with the proper Core Data version, and manually migrate using the old format for read and new format for write.Grimona
I didn't make any changes directly to my data model, but I have pinpointed the problem. I was retrieving my NSManagedObjectModel using [NSManagedObjectModel mergedModelFromBundles:nil] which merges ALL data models present in the bundle. This included all data models that came with the XMPPFramework, and now that the framework has been removed, the NSManagedObjectModel that is passed into [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel] is different, thus causing the crash. This is a pretty unique problem,I'm not sure if anyone has any suggestions for how to perform a migrationLownecked
Comments are the wrong place to add details... can you please edit the question and add to it the relevant information that is contained in the comments?Quemoy
M
9

Actually you might have updated xcdatamodel somehow after first version, And you didn't created a new xcdatamodel model for second version. So on second update it's crashing.

NOTE: After first version release, you have to create a second model version of xcdatamodel.

To create second model version of xcdatamodel -
1. first you have to select Model.xcdatamodeld -> Go to Editor on menu -> Add Model Version. Here you have to name a model version and based on which old model you want to create this new one.
Now whatever changes you want to make you should make on new model version xcdatamodel.

enter image description here

2. You can see on image, I've given a new name to my new model 'Model2.0', which is based on my previous 'Model'.
New model will work exactly like your old model, Additionally changes will be made on new model won't affect to your old model. So it won't crash your app after update.
3. You have to select your new 'Model2.0' as a default working model. For that please consider the below image.

enter image description here

4. Here you can see there is 2 model now. Please select 'Model.xcdatamodeld' a main model, and open it's 'File Inspector' on right side - as opened on above image.

5. There is 'Model Version' field on the right side, Which indicates the 'current' model selected on this project. Please select the new model 'Model2.0' for your updated version. Now you can run and it will work fine onwards.

NOTE: Please make sure now whatever changes you will make, you will do it on your new model 'Model2.0', So it won't conflict with your old model. You have to make new model each time, if you want to change configuration of xcdatamodel on updated app version.

Mentholated answered 3/8, 2015 at 13:50 Comment(1)
I made changes in old version but discarded now. i am still having same error. any help?Runthrough

© 2022 - 2024 — McMap. All rights reserved.