Realm Database Overview
Realm is a cross-platform mobile database solution designed for mobile applications. It’s fast, lightweight, and quite simple to integrate into your project. Furthermore, it doesn’t rely on Core Data or a SQLite database. The Realm developers claim that their data storage solution is faster than SQLiteas well as Core Data.
Problem
When we modified our model’s properties to store data in realm database then app get crashed and Xcode’s console output told us Migration is required due to the following errors:
. In order to solve this issue, We need to add migration to our project.
Solution
Our app crashes because there is a mismatch between what we define in code and the data exists on disk if we had saved any data with the older model version. When this happens, an exception will be thrown when we try to open the existing file. The solution is to define a migration and the associated schema version by creating a Realm.Configuration
instance.
The migration block provides all the logic for converting data models from old schemas to the new schema.
1 2 3 4 5 6 7 8 9 10 |
let config = Realm.Configuration( // Set the new schema version. This must be greater than the previously used // version (if you've never set a schema version before, the version is 0). schemaVersion: 1, migrationBlock: { migration, oldSchemaVersion in if oldSchemaVersion < 1 { // Apply any necessary migration logic here. } }) Realm.Configuration.defaultConfiguration = config |
Example
We have a data model that stores a user in Realm Database
1 2 3 4 |
class User: Object { dynamic var name = "" dynamic var age = 0 } |
Then if you have to make some changes in user’s properties
1 2 3 4 5 |
class User: Object { dynamic var name = "" dynamic var age = 0 dynamic var email = "" } |
Because our previous model version doesn’t have the email
property, we can do the migration by calling Migration
‘s enumerateObjects
method within the migration block and assign an empty email string to the existing data.
1 2 3 4 5 |
if oldSchemaVersion < 1 { migration.enumerateObjects(ofType: User.className()) { (_, newUser) in newUser?["email"] = "" } } |
Secondly, we want to rename the name
property to fullName
. The migration can be done by increasing the schema version and invoking Migration
‘s renameProperty
method inside the migration block. It’s important to make sure that the new models have a property with the new name and don’t have a property with the old name.
1 2 3 |
if oldSchemaVersion < 2 { migration.renameProperty(onType: User.className(), from: "name", to: "fullName") } |
Finally, we would like to separate the fullName
property into firstName
and lastName
. We enumerate each User
and apply any necessary migration logic. Don’t forget to increase the schema version as well.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
if oldSchemaVersion < 3 { migration.enumerateObjects(ofType: User.className()) { (oldUser, newUser) in guard let fullname = oldUser?["fullName"] as? String else { fatalError("fullName is not a string") } let nameComponents = fullname.components(separatedBy: " ") if nameComponents.count == 2 { newUser?["firstName"] = nameComponents.first newUser?["lastName"] = nameComponents.last } else { newUser?["firstName"] = fullname } } } |