365SplendidSuns
365SplendidSuns

Reputation: 3245

Update iOS Core Data Version to Avoid a Crash

I updated my iOS app and this included making a number of changes to the Core Data model. Then after I uploaded the new version to the App Store and people started trying to use it the app crashed!

I now understand that this is because the users had the old Core Data on model on their devices and it isn't compatible with the new one. I've read that I should have updated the model version so now that's what I'm doing.

I'm slightly nervous about it though as I've read that I should have updated the model version BEFORE making the changes. Obviously I can't go back in time - the changes are made and I didn't update the eversion BEFORE I made them. So will it be ok to just change the model version now and expect it to work ok on my users devices without crashing or is there something else I can / must do?

The actual data isn't very important and will soon be replaced so I don't care if they can keep the data or not. I just need them to be able to update the app without it crashing when they next try to use it.

Upvotes: 0

Views: 1887

Answers (3)

shima
shima

Reputation: 33

Swift 3

    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory.appendingPathComponent("name.sqlite")
    let walUrl = url.deletingPathExtension().appendingPathExtension("sqlite-wal")
    let shmUrl = url.deletingPathExtension().appendingPathExtension("sqlite-shm")
    do {
        try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
    } catch {
        do {
            try FileManager.default.removeItem(at: url)
            try FileManager.default.removeItem(at: walUrl)
            try FileManager.default.removeItem(at: shmUrl)
            try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
        } catch let error as NSError {
            //handle error
        }
    }

Upvotes: 1

Leonardo
Leonardo

Reputation: 1750

If you are using any version control system, you can retrieve the old model and do it the right way, follow this documentation to do so.

In order to stop the users app from crashing, you can erase the old sqlite file and generate a new one using the updated model.

You can do something similar to this code. Notice that this will erase the sqlite file every time your app is not able to open it

__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];

if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) 
{
    if(error)
    {
        //Erase old sqlite
        [[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];

        //Make new persistent store for future saves 
        if (![self.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
            // do something with the error
        }
    }
}

Upvotes: 4

Eliza
Eliza

Reputation: 212

When so ever you make changes with Core Data model, you have to go through complete migration process before uploading new version. Otherwise it will work only for new user and old user will get crash. Now you have to migrate your data model to new version and then upload the build again. This is the only solution, for more just read this link :

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmMigrationProcess.html#//apple_ref/doc/uid/TP40004399-CH6-SW1

Upvotes: 0

Related Questions