How to migrate one-to-one relationship to one-to-many relationship in Realm Swift

Viewed 97

Currently, I have two custom model classes. Between them previously I set up a one-to-one relationship. But now due to new requirements change, I need to convert the relationship into a one-to-many.

For example, this is how I previously structure my model classes

class Location: Object {
  @objc dynamic private var id: String = NSUUID().uuidString
  @objc dynamic var typeString: String = 

}

class Job :Object {
@objc dynamic var id: String = NSUUID().uuidString
let location: Location?
}

New structure

class Job :Object {
@objc dynamic var id: String = NSUUID().uuidString
let locations = RealmSwift.List<Location>()
}

So basically I want to save multiple location objects inside Job class. This new structure is working fine for me. But now I want to migrate old data into this new setup. I try to achieve this using the following code but no success.

migration.deleteData(forType: Location.className)
migration.enumerate(ofType:Job.className) { oldObject, newObject in
    let location = migration.create(Location, value: oldObject!["location"]!)
    (newObject!["locations"] as! List<MigrationObject>).append(location)
}
1 Answers

In a nutshell, you have a one to one relationship and you want to now convert that to a one to many relationship (via a List), using the existing location as the first object in the list.

A getcha is you can't have two objects with the same primary key so during the migration process, the old locations have to be removed and will be replaced with a new location with the same properties (and primary key) and then add it to the Job's locations List property.

Here's the code:

let config = Realm.Configuration( schemaVersion: vers, migrationBlock: { migration, oldSchemaVersion in
     if (oldSchemaVersion < vers) {
        migration.deleteData(forType: Location.className()) //delete all locations
        migration.enumerateObjects(ofType: Job.className()) { oldItem, newItem in
           let existingLoc = oldItem!["location"]
           let updatedLoc = migration.create(Location.className(), value: existingLoc)
           let locList = newItem!["locations"] as! List<MigrationObject>
           locList.append(updatedLoc)
        }
     }
 })
Related