0

I released an app using core data to store some important information. Recently I decided to re-do my data model to bring it up to date and make it easier to use.

I added some entities to the data model, and it runs fine in the simulator - however when I released it to the beta testers as soon as it tries to do anything with core data it is crashing.

I did not create a new version of the data model.

I have read here and here about how to deal with this error but both answers reference code that I do not have anywhere in my app, but they seem to have built in - they also talk about lightweight data migration? A lot of the answers reference a NSPersistentStoreCoordinator, which I do not have/know how to implement.

The code I have in the app delegate dealing with the persistentContainer is:

lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "App_Name")
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

The other answers also referenced crashes in the simulator which required re-installation - I don't think I got these, but I may not have noticed.

What is the best way for me to update my data-model such that my users won't get crashes?

EDIT:

I have updated the persistentContainer to this:

lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "App_Name")

    let myFileManager = FileManager()

    do {
        let docsurl = try myFileManager.url(for:.documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
        let myUrl = docsurl.appendingPathComponent("UserDataTA")

        if try myFileManager.contentsOfDirectory(atPath: docsurl.path).contains("UserDataTA") == false {
            try myFileManager.createDirectory(at: myUrl, withIntermediateDirectories: false, attributes: nil)

            try container.persistentStoreCoordinator.addPersistentStore(ofType: NSInMemoryStoreType, configurationName: nil, at: myUrl, options: nil)
        }
    } catch {
        print(error)
    }

    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            fatalErrorText = error.debugDescription
            firstFuncs.errorAlert(error: fatalErrorText)
        }
    })
    return container
}()

however now the error message is "Error Domain=NSCocoaErrorDomainCode=134140 'Persistent store migration failed, missing mapping model.'"

ZiEiTiA
  • 275
  • 2
  • 16
  • Are you creating new versions of your data model every time you change something? – sschale Aug 03 '17 at 03:20
  • @sschale no I am not and I've gathered that this is the problem, but I don't know how to go about fixing it – ZiEiTiA Aug 03 '17 at 09:53
  • What's the crash log? – Amin Negm-Awad Aug 03 '17 at 09:53
  • @AminNegm-Awad - there isn't much of a crash long since the crash happens to the beta testers - all i get is `_TTSf4d_n___TFFFC20App_Name11AppDelegateg19persistentContainerCSo21NSPersistentContainerU_FT_S1_U_FTCSo28NSPersistentStoreDescriptionGSqPs5Error___T_ + 512` – ZiEiTiA Aug 03 '17 at 11:46
  • Possible duplicate of [iPhone Core Data "Automatic Lightweight Migration"](https://stackoverflow.com/questions/1830079/iphone-core-data-automatic-lightweight-migration) – sschale Aug 03 '17 at 23:29
  • @sschale not a duplicate as they are a few steps ahead of me when they asked their question - but it looks like the answer provided to them might be useful here. Their question is also in obj-c not swift. – ZiEiTiA Aug 04 '17 at 09:24
  • @sschale edited – ZiEiTiA Aug 04 '17 at 09:36
  • All the steps you need to do are language agnostic - have you been creating new model versions? – sschale Aug 04 '17 at 16:35
  • @sschale I have not, however I tried to create a new version and restore the original version to what it was like at release but still haven't solved the crash. – ZiEiTiA Aug 04 '17 at 18:05
  • Sounds like you need a data migrator. – NRitH Aug 04 '17 at 18:13
  • @NRitH - if you have a solution or a start of one please put it in an answer. – ZiEiTiA Aug 04 '17 at 18:19

1 Answers1

0

Your crash sounds like it's happening because your data model changed, and any existing data that exists on a device can't be mapped 1:1 to the new model. This is where data mapping and migration comes in. Apple's docs are a good place to start. The very high-level overview is:

  1. Open your xcdatamodel or xcdatamodeld file in Xcode, then select "Add Model Version...".
  2. If necessary, save your model as an xcdatamodeld file. (The d suffix indicates that it's versioned.)
  3. Note that your xcdatamodeld file is really a folder, and it includes multiple xcdatamodel files. All versions after the first one will include a numeric version number in the filename.
  4. Make your model changes in the new model version.
  5. If the changes are relatively simple (such as renaming an entity or adding or removing attributes), then it's considered a lightweight migration, and core data can figure out how to do the migration itself.
  6. If your changes are more involved (such as splitting an entity type into two), then you must create a mapping model.
  7. Add the code to perform the migration at startup time.

Obviously there's a lot more to this process, but this may give you a decent start.

NRitH
  • 13,441
  • 4
  • 41
  • 44
  • This looks good and I understand the progress - the 2 problems I'm having are: • Reverting the first data model back to the version that the external testers are using • Performing the migration at startup. I had a look at the documentation but couldn't get very far with it. – ZiEiTiA Aug 04 '17 at 18:41