In the latest version of my app, I added 1 new column to an existing table. Nothing major, just a simple flag. I bumped the data model version and set it to be the active model and I've been using the automatic lightweight migration strategy successfully for the last several app updates.
A small minority of users have reported that after upgrading to the latest version of my app, they lose all their data and the app crashes any time it tries to write/read to/from CoreData. I cannot replicate the issue.
Why would auto migration work for most, but not all users?
Answer
In this specific instance, the issue ended up being that I had accidentally modified an xcdatamodel file that was several versions old without knowing it. When I released a new version of the app, there were a handful of users that had not updated for a very long time, and therefore the "most recent" version of the xcdatamodel they had was the same as the file that I accidentally changed. When migration tried to happen on their devices it choked because the version of the data model file that it wanted to base migration on had been modified.
To fix this, I had to identify what I changed in the old xcdatamodel file, undo the change, and release an app update. Once users affected by this updated to the newest version, migration worked.
Additional Information:
The only thing they all seem to have in common is they are all running iOS 6.1.3. I cannot replicate this myself. I have a device running iOS 6.1.3 but no matter how many times I do the upgrade from one version of my app to the next, it works. I've even tried skipping a couple versions and upgrading from an old one to the newest and it worked fine.
For what it's worth, I'm using the auto-migration strategy outlined in this post and it has been working fine for the last 8 or 10 app updates, including some major new things added to/removed from my CoreData model.
Related
My CoreData model currently uses old (Xcode 3.2) format. I'd like to increase it to the latest one available, in which data is represented in the XML form:
Should I also increase the Model Version Number in the Core Data editor?
I cannot think of any reason why you'd need to do that as Model Version and Tools Version should be unrelated and orthogonal.
I have a 10-year old Mac app, Core Data document, which I've always built with the latest Xcode but I never bothered to change the Tools Version in its one data model, which contains 28 entities and a lot of relationships. Until 30 minutes ago, its Tools Version was Xcode 3.2, like yours. To prove my point, I changed only the Tools Version, to Automatic (Xcode 9.0), did a Clean Build Folder, then test, build and run. It passed my test suite, launched fine, opens documents, saves changes. No trouble found. Everything works fine. I plan to commit this change and ship my next version with it.
I have created an app that crashing when tried on testflight to update from build 54 to 55. But if I delete the app first, then install the build 55 it runs smoothly. so I build another one with some fixes inside and try it on test flight, so now build 55 - 56 update. it runs smoothly.
so the problem is that when updating from 54 to 55 something off, is anyone here has had the same problem?
More often than not, if you have a crash on an update and not on a fresh install, it means that you have some persisting data that is not compatible with the state of the updated app.
The most common cases are :
Database data is not migrated properly (or not migrated at all) ; maybe between the two updates some of the fields changed in code and are not compatible with older database version?
Keys & values in keychain and/or userdefaults. Same as the database, your code is expecting some values but the file from the previous versions does not know those values.
Files. You might be writing/expecting some files formatted in a specific way, or containing specific data. But users from earlier versions might not have those files, and therefore would cause a crash
Basically, anything that persists can cause crashes or bugs when updating to a new version. But because you're testing from a fresh install, you always get the correct formats during your tests.
If you have a crash, there should be a very clear exception telling you what happened which can help you locate the issue, and why it happened. It should be pretty simple from there to isolate the files that require migrations.
Good solutions to avoid that is to test using previous versions installed, and keep track of all persistant modifications that you make. Once you decide something that has to persist, you have to take it into account once you decide to change it. You'll probably have to write some code to update the file and check its version before accessing it. So if database version 1 had two tables and three fields, you have to know it, and if you're not happy with that, you have to write code to update the database, all of its contents, and then only you can expect everyone to have the new database.
This is also another good idea : use versioning inside your app. If your app is version 40, but your file is still in version 34 format, you have to update it to version 40 using code specific for that update.
Migrating is not an easy task. Requires a lot of testing and data manipulation. I strongly suggest you use unit tests for that kind of work before pushing into production.
Predictably, my app won't have changes in its data model in future updates, but just in case... will it be a problem to deliver the first version of the app without having set its Model Version, and then starting setting it in subsequent app versions only if migrations needed? Or should I deliver the first version of the app having already set a Model Version?
Thanks
Yes, maybe you don't need enable versioning in the first version.
BUT, for example, if you enable it in the second version, and forgot change CoreData initializing code?
I prefer add automatic version migrating since first version of app, even if I don't plan to change model
I have strange issue which is because that I forgot to change Core Data model version for an update of my application. Now I have an app on AppStore lets say version 1.0. And for version 1.1, I've changed the Core Data Model without creating 2nd version of it. I'm using Magical Records which deletes the previous Sqlite file in case of conflict.
My app is on iOS 7 which uses Journal mode (Write ahead log, wal file) and I can't use my old sqlite file for data.
For some reason I can't push an update 1.x in which I save all my data somewhere else and backup on 2.0, when conflict happens.
The issue is I don't want to loose my previous data. What to do ?
There are two methods to solve this:
Remove 1.1 from AppStore to avoid unecessary updates for existing users. Add missing model version (I hope You used SVN, GIT or any other source versioning tool?), theoretically you can manually revert all your changes to make model look same as 1.0 had, and then create version for 1.1. Submit new app version supporting migrations from 1.0.
Remove 1.1 from AppStore as above. Manually migrate data from old SQLite store using FMDB or any other framework for direct sqlite access. Read all data via SQL and insert them in CoreData store using CoreData methods.
I have done lightweight versioning in my project, right now i have two versions and the current version is set to latest one(dataModel 2.xcdatamodel for example). I have followed every steps there in the apple document. But it's crashing every time because the old version is loading(found that after debugging, the new attributes are missing in the entity) after fresh installation.
If i switch back to old version and roll back to current version again then it's running fine. I have deleted the references and added it again but the result is same.
My source code is on git and its very annoying to do that extra effort every time. Please help me to solve this problem.
thanks :)
If you are 100% sure that the new version is loaded, it means that you created the new version, started the app, applied changes to the model, started the app again. To eliminate the possibility of it, just create the 3rd version based on the 2nd version and make it current active. Also make sure you have the automated lightweight migration implemented as per apple manual here
https://developer.apple.com/Library/ios/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmLightweightMigration.html
I am not sure, i guess it is a git/svn problem. We had to work with different versions of Xcode from the very beginning of the project. Whenever we committed to the git, the git found a miss match of Xcode versions(for say i am working with Xcode 5.1 and my team mate working with Xcode 5.0.1, the project was initialised with Xcode 4.1) and set the current core data version to the very older one that is dataModel 1.xcdatamodel in my case. That's why the project was running fine in my side but when my team mate pulled my code from the git and tried to run in his side it crashed everytime because the version was set to older one by the git.
I got this from here. After following the instructions the problem is solved for now.
Thank you all. If you have any better solution please share.