Minimize Crash-On-Launch Risk By Core Data Migration in iOS App

0
Shares
Minimize Crash-On-Launch Risk By Core Data Migration in iOS App
Rate this post

Core Data Migration Tutorial iOS App

Recently, while working on one of our client’s project, we encountered an annoying issue.

Whenever we modified the data model of client’s app, the persistent store became incompatible with app’s data model.

This resulted in crash on launch or/and rendering the app became unusable.

And it is a common issue actually. Whenever you develop a core data app, you design an initial data model in the beginning. But at some point, you may need to make changes to your data model. But when you make such changes, most of the time app crashes.

So how do you solve this?

There are two options to solve it, one is by migrating the persistent store and second is creating a brand new persistent store for the modified data model.

Good, But Is It Possible To Avoid a Migration?

Well, there are few cases where you can actually avoid a migration. Suppose an app is using core data in the offline cache, now when you upgrade your app, then you can easily delete and re-develop the entire data store.

However, this is only possible if your users’ data isn’t in the app’s data store. In rest cases, yes you have to implement the core data migration.

How Exactly The Migration Happens?

Basically the Core data migration happens in three steps:

1) Core data copies all objects from initial data store to the next.

2) After that, core data finds relates and connects all the objects according to the relationship mapping.

3) Lastly, it enforces any data validations in the final data model. Core data disables the final data model validations during data copy process.

Now if you’re wondering what if something goes wrong while migrating?

Well don’t worry, the Core data migrations will remove core data only when the migration is successful. So even if something goes wrong, then it keeps the original data store.

Getting Started

Create a new project under file menu and select “Single View Application” and click on next.

Core_migrate1

 

In the next tab, give name to your project and keep the “Use Core Data” option ON.

Core_migrate2

Next, add an Entity (student) and “Attributes” by name “fname” & “lname”.

Core_migrate3

 

By keeping the check box ON of “Use Core Data” it will create core data managedObjectModel, persistentStoreCoordinator, managedObjectContext, saveContext objects/methods in AppDelegate class.

Add following code snippet for Migration option in persistentStoreCoordinator method as follow.

let optionMigration = [NSMigratePersistentStoresAutomaticallyOption: true,

                        NSInferMappingModelAutomaticallyOption: true]

Now, change:

try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)

To:

try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: optionMigration)

Now take the complete snippet.

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {

        let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)

        let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")

        var failureReason = "There was an error creating or loading the application's saved data."

        let optionMigration = [NSMigratePersistentStoresAutomaticallyOption: true,

                        NSInferMappingModelAutomaticallyOption: true]

        do {

            try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: optionMigration)

        } catch {

            // Report any error we got.

            var dict = [String: AnyObject]()

            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"

            dict[NSLocalizedFailureReasonErrorKey] = failureReason

            dict[NSUnderlyingErrorKey] = error as NSError

            let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)

            NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")

            abort()

        }

        

        return coordinator

    }

To create NSManagedObject Subclass go to Menu bar Editor -> Set NSManagedObject Subclass and click on that.

it will show you model and Entity selection screen for create subclass of managed object.

Core_migrate4

Now to add First name & Last name in core data, use following code.

extension Student {

    @NSManaged var fname: String?

    @NSManaged var lname: String?

    

    

    class func createInManagedObjectContext(moc: NSManagedObjectContext, firstName: String, lastName: String) -> Student {

        let newItem = NSEntityDescription.insertNewObjectForEntityForName("Student", inManagedObjectContext: moc) as! Student

        newItem.fname = firstName

        newItem.lname = lastName

        return newItem

    }

}

Save Item in index by:

Student.createInManagedObjectContext(moc, firstName: fName, lastName: lName)

Now go to Project navigator and Select core data model then go to Menu bar Editor -> Add Model Version,

Set version name and press Finish.

Core_migrate5

However, you need to change model version. Go to Project Navigator, then open the Utilities panel on the right-hand side of Xcode, and select the first tab – the File Inspector.

Here under “Model Version” there is a dropdown where you can select the new version 2 of the model, as shown in the figure below.

Core_migrate6

Now we can add “fullname” mission attribute of Student entity.

@NSManaged var fname: String?

    @NSManaged var lname: String?

    @NSManaged var fullname : String?

    

    class func createInManagedObjectContext(moc: NSManagedObjectContext, firstName: String, lastName: String, fullName: String) -> Student {

        let newItem = NSEntityDescription.insertNewObjectForEntityForName("Student", inManagedObjectContext: moc) as! Student

        newItem.fname = firstName

        newItem.lname = lastName

        newItem.fullname = fullName

        return newItem

    }

Save Item in index by:

Student.createInManagedObjectContext(moc, firstName: fName, lastName: lName, fullName: "\(fName) \(lName)")

We are done!

If you face any issue implementing this demo, you can contact our developers for help.

Migrations are important if you’ve planned of using core data extensively in your startup app.  Migrations basically allows you to safely modify your core data to a new data model without having to lose original core data. So in case you’re a technical person and looking for help, you can hire iPhone app developer from us.

We’re an award winning iPhone app development company with more than 200+ developers. Throughout our journey, we’ve worked with many successful startups and helped them overcome their app issues.

Grab a free copy of Core data migration demo from Github.

 
0
Shares
 

LET'S TALK VALIDATE YOUR IDEA!