1

I am facing a migration of a Realm backed object for a large and long running app. The object has gone through several property migrations in its lifespan and has recently been removed from the app altogether.

As Realm migrations happen in a linear approach from oldest to newest schema version I understand a user coming from several versions old app will migrate through all versions one by one before reaching the latest. This has never been in issue in the past, I'm just wondering what approach is needed when now that object will no longer exist in the latest version, so previous migration class references cannot be found.

A simplified example.

V1 schema

class Customer: Object {
    @objc dynamic var customerId: String?
    @objc dynamic var surname: String?
    @objc dynamic var givenName: String?
}

V5 schema

class Customer: Object {
    @objc dynamic var customerId: String?
    @objc dynamic var surname: String?
    @objc dynamic var givenName: String?
    @objc dynamic var fullName: String?
}

V16 schema

class Customer: Object {
    @objc dynamic var customerId: String?
    @objc dynamic var surname: String?
    @objc dynamic var givenName: String?
    @objc dynamic var fullName: String?
    @objc dynamic var lastVisited: Date?
}

V20 schema

//Customer object does not exist anymore

Example migration through schema versions

migrationBlock: { migration, oldSchemaVersion in
    if (oldSchemaVersion < 5) {
        migration.enumerateObjects(ofType: Customer.className()) { oldObject, newObject in
            let givenName = oldObject!["givenName"] as! String
            let surname = oldObject!["surname"] as! String
            newObject!["fullName"] = "\(givenName) \(surname)"
        }
    }

    if (oldSchemaVersion < 16) {
        migration.enumerateObjects(ofType: Customer.className()) { oldObject, newObject in
            if let newObject = newObject {
              newObject["lastVisited"] = Date()
            }
        }
    }

    if (oldSchemaVersion < 20) {
      //I want to delete all Customer data for an object that no longer exists
    }
}

My issues now are:

  1. Build errors will exist on the migration lines with enumerateObjects(ofType: Customer.className()) as Customer does not exist anymore.

  2. The properties being migrated in v5 and v16, and all the other Customer properties do not exist anymore. Does this matter?

  3. I want to delete all data in v20 and remove the Customer object.

My thoughts:

  1. Do I go back and modify older previous migrations to instead use the string name instead of className? eg.
enumerateObjects(ofType: "Customer")
  1. Given that I no longer care about the customer properties in earlier migrations and any user updating will end on V20 is the final migration as simple as:
migration.deleteData(forType: "Customer").
  1. What will be the experience for a user moving from v5 -> v20?
Daniel Bowden
  • 988
  • 1
  • 10
  • 23
  • I think you can indeed just do `migration.deleteData(forType: "Customer")` and not do anything else for `oldSchemaVersion < 16` or `oldSchemaVersion < 5`. Why not try it out? – Sweeper Jul 15 '21 at 03:55
  • Sorry I have tried tried it out, that's why I mentioned the <16 and <5 migrations would have build errors for the Customer.className() references. I guess my two main questions are, is it good practice to go back and modify old migration code and is there any harm in doing so? And then can I delete all data based on the string class name (which you answered, thank you) – Daniel Bowden Jul 15 '21 at 04:14
  • You want to use new Customer object instead of old? – Jignesh Mayani Jul 15 '21 at 04:53
  • You have added new values in your old object and you have migration issue, right? – Jignesh Mayani Jul 15 '21 at 04:54
  • Sorry @JigneshMayani I'm not sure I understand your questions. I have added multiple new values over the lifespan of this object (100+) app versions and there have been many successful migrations during this time. Now I am deleting this object in the latest app version. The above is a simplified example. – Daniel Bowden Jul 15 '21 at 05:13
  • Sorry @DanielBowden for the inconvenience. Have you tried with deleteRealmIfMigrationNeeded while configure realm? I also have an issue with migration in past and I am using this "Realm.Configuration(deleteRealmIfMigrationNeeded: true" to resolve the migration issue. – Jignesh Mayani Jul 15 '21 at 05:20
  • I hope this helps. – Jignesh Mayani Jul 15 '21 at 05:20
  • @DanielBowden I need to delete realm because of my old objects dose not have new fields and I have an issue in the new object after added new values in my old object. So that's why I have to remove the realm object. – Jignesh Mayani Jul 15 '21 at 05:23

0 Answers0