Realm Migration — Renaming a class and migrating nested objects

Introduction

Usually, to rename a class the only thing we have to do is “Cmd + Maj + A”, and then “Rename”, but in the case of Realm, it’s a little bit more complex as we have to do a migration to avoid user datas losts.

For this article, I’ll take this example:
we have two classes (User and Sport) and here is the Realm objects structure before the migration:

Realm objects structure before the migration

Every sport has an ID, a name and a list of User, and every user has an ID, a first name, a last name and a Sport object.

Here is the Realm objects structure that I want at the end of the migration:

Realm objects structure at the end of the migration

So, instead of storing a Sport object for a user, I intend to save only the ID of the sport. And for the Sport object, I don’t want to save the list of users anymore.

Also, I wanted to rename both classes and prefix them by R (R for Realm), because I intend to reuse the old classes name in my current code, for my UI objects.

Before starting the migration, I created the new classes (R classes) in my project and I removed the old ones (then, I also updated the application to be able to compile my project).

Let’s start the migration now!

To complete the migration and reach my goals, there are two steps:

  • Rename both Realm classes in the database
  • Don’t forget to migrate the user’s data!

Renaming a class

So, the truth is that we are not renaming a class, but we are creating a new class from the new object. Then, we migrate the user’s data and at the end, we remove the old object.

“Renaming” a Realm class and migrating the user’s data

I’m going to explain the different steps:

  • Lines 2 to 4: We recover the old object information (in this case, the ID and the sport’s name)
  • Line 6: We ask the migration object to create the new R object (RSport)
  • Lines 7 and 8: We associate the old object’s values to the new object to keep all user’s information
  • Line 10: We remove the old object (Sport), as we don’t need it anymore

We’ve done the “renaming” of the first Realm object (Sport to RSport).

Now, let’s get the migration started, with a more complex object (this object contains another Realm object in it, so it’s a little bit different)

Migrate a complex Realm object included in another Realm object

First migration step: create the new object and migrate attributes

Again, like the Sport object, we loop on all old objects of the database, we get all the datas, we create new objects, we copy the data and then, we remove the old object as we don’t need it anymore.

Well done, but if we stop here, we loose the user’s sport…

The problem: how to get the id of the Sport object inside the User object that we want to migrate?

If we try to do it like all others attributes, we do this:

Recovery of the Sport object from the User object in type“Any”

We get an object of type Any:

Sport object data from the User object

We can’t cast the object to the Sport type, as this class doesn’t exist anymore (remember, we deleted it before starting the migration process). Also, we can’t cast it to RSport type, because this class is not equivalent to the Sport type.

(But we can still see all information; that’s a good start!)

The only type in which we can still cast the object, it’s a type that the application still has. As we are working with Realm, and that all Realm objects inherit from the object “Object”, we can cast our object to the “Object” type:

Sport object from User object casted to Realm object

We haven’t made progress here, as we didn’t have access to the ID of the Sport object yet.

If we try to do like the previous attribute, the compilator returns an error:

Compilation error when we try to access to the Sport ID of the user like a key value dictionary

The solution:

Use the value(forKey:) function, that allows us to get the ID value of the old Sport object:

One solution to get the ID of the Sport object from the User object

So, we finally have:

The final solution

Like this, you can access an object contained inside another object when you do a Realm migration. By the way, here, it was a simple example, but you can also apply this solution to object inside object inside object, etc.

What’s next?

Thanks for reading,

Happy coding!

Author: Alexandre Cools
https://twitter.com/Alexandre_Cools

Lunabee Studio is a company creating premium mobile Apps in the Alps. We love mobile UX, iOS and Android. Follow us to keep up with our latest publications and news.

This is Lunabee Studio’s account, on which we share content on various topics, including of course Mobile Apps’ creation.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store