-->

Preventing a CoreData crash for upgrading users

2019-05-30 06:11发布

问题:

I built an app about a year and a half ago that I'm coming back to. It was the project I cut my Swift teeth on and obviously a lot has changed since then, both in the language and my Swift abilities.

Yesterday for the first time, I updated my single CoreData model to add an optional string attribute. I did the file generation bit and made sure in the inspector column the new data model is appropriately selected.

On my Simulator and testing devices, I need to delete the old version of the app to install the new version or I get a crash. I assume that's just part of the development environment process. How can I ensure that upgrading users won't have to delete and reinstall when they do a simple update from the App Store? I assume that Xcode/CoreData/Apple have this handled with some internal scripts or processes that are invisible to the user, "it just works." But I wanted to post this here to understand if there's anything additional I need to do to ensure a smooth transition from v1 to v1.1 for the user.

All I did was an an optional string column, as I mentioned. I assume that all existing user data will be migrated over to the new schema with the new field being nil.

Any thoughts here would be very welcomed and appreciated. Thanks!

回答1:

If your app is crashing in the Simulator when upgrading, your users will have crashes too.

To avoid this, you need to make sure you follow these steps:

  1. Make sure you do NOT change the original version of your data model in any way.
  2. In Xcode, select your xcdatamodel file, then from the menu choose Editor > Add Model Version...
  3. Xcode will suggest a new version name, based on the current model. Make a mental note of the new version name, then click Finish.
  4. Select the xcdatamodel file again, go to File inspector and under Model Version, select the new version name to make this your current version.
  5. In Project Navigator, select the new version of the xcdatamodel. Add your attribute.

It's important to follow these steps in this order. If you add your attribute before creating the new model or making it your current version, you will have crashes.

EDIT: This will only work if you enable lightweight migrations. This is a code snippet of how to do this:

let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]

do {
    //coordinator is an NSPersistentStoreCoordinator
    try coordinator!.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: options
} catch var error as NSError {

  // handle error however you want here...            
  abort()
}