Saving Images in Core Data L5.5.1

A common rule of thumb when saving images to a database. If the image is really small, then save it directly to the database, if it's big save it in a file and save the name of that file or path to the file in the database. With Core Data we don't have to bother with implementing either, it takes care of all the details by just selecting an option in the data model.

Modifying The Model

We can't save the image as an instance of UIImage because Core Data doesn't have any knowledge of what that is. Instead we need to save images as binary type which means using iOS's Data type.

In our case every Note will have a PhotoFrame and each PhotoFrame might have a single imageData. The imageData property will be optional as it might be empty.

imageData optional

To create the relationship between Note and PhotoFrame we need to setup the properties and delete rules. We must uncheck Optional as each Note must have a PhotoFrame and delete rule should be that when we delete a Note we delete the PhotoFrame so we change it to Cascade

note not optional

In setting up the inverse relationship between the PhotoFrame and the Note the Optional property should be false because we don't want a PhotoFrame if it's not connected to a Note. The delete rule should be Nullify because when we delete a PhotoFrame we don't want to do anything to the Note.

photoFrame not optional

Model Versions

If there were previously saves objects in the database you will get an error from xCode saying something about the store used to create the new model is not the same.

To fix this we need to create a new model version. To do this we select "Add Model Version" from the Editor tab. We can call it whatever we want.

add model version

After we create a new model version we can see it in the file navigator, but there is a problem because the old model version is still set to the current version.

new model version

To change the current model version select the Model.xcdatamodelId in the file navigator and in the file inspector change the Model Version selector.

change model version

Ideally we would create the new version first, but if we didn't we will need to add all the changes we made to the new version.

The last step is to make a minor change in our Core Data Stack file to make sure it performs the migration from version one to version two. By adding the code below create two options in the form of a dictionary and add them to the persistent store coordinator.

NSMigratePersistentStoresAutomaticallyOption tells the coordinator to perform the migrations automatically.

NSInferMappingModelAutomaticallyOption tells xCode to figure out how to make the migration from version one to version two happen.

        // Options for migration
        let options = [NSInferMappingModelAutomaticallyOption: true,NSMigratePersistentStoresAutomaticallyOption: true]

        do {
            try addStoreCoordinator(NSSQLiteStoreType, configuration: nil, storeURL: dbURL, options: options as [NSObject : AnyObject]?)
        } catch {
            print("unable to add store at \(dbURL)")
        }