I am trying to migrate our Realm Swift schema from using a String wrapper class to the primitive String for collections. I am running into issues extracting the string values from the wrapper during migration.
Here is the wrapper class:
class StringDB: Object {
@objc var stringVal: String = ""
convenience init(string: String) {
self.init()
stringVal = string
}
}
Then I have an example class with a List<StringDB> property:
class MyObjDB: Object {
var emails: List<StringDB> = List<StringDB>()
@objc dynamic var id: String = UUID().uuidString
convenience init(_ emails: [StringDB]) {
self.init()
for email in emails {
self.emails.append(objectsIn: emails)
}
}
override static func primaryKey() -> String? {
return "id"
}
}
that I want to convert to a List<String>.
Here is my migration code.
let config = Realm.Configuration(schemaVersion: latestSchemaVersion, migrationBlock: {
migration, version in
if version < 2 {
migration.enumerateObjects(ofType: MyObjDB.className(), { old, new in
guard let old = old, let new = new else { return }
let oldEmails = old["emails"] as! List<StringDB>
let newEmails = List<String>()
for email in oldEmails {
newEmails.append(email.stringVal)
}
new["emails"] = newEmails
})
}
})
However, the let oldEmails = old["emails"] as! List<StringDB> cast fails. I've tried also casting the collection to List<MigrationObject> and then casting the individual objects to StringDB but that cast fails as well.
I've found a workaround that may be satisfactory (I haven't confirmed yet), of converting the MigrationObject directly to string using coercion like "\(email)" and then running a regEx that will extract a desired substring from the garbage (StringDB {\n\tstringVal = [email protected];\n}), but I have no idea yet whether that will hold up in production, and I would prefer to work with something resembling a recommended way for doing this migration.
The Realm version is not shown in the question and there are a few typo's in the code. For older Realm versions,
Listsshould be defined thusly:then newer versions should be this:
Then this is a problem as it iterates over the emails array count times and appends the entire emails list over and over for every email in that list.
Also, when using older Realm versons with @Objc property types, they need to include
dynamic. So on theStringDBobject thisshould be this
Lastly, the
MyObjDBneeds to have somewhere to put the new email list. You can't overwrite the old one as it's not the correct type. So add a propertyThen to the question: See comments in code for the flow
How about this: