Reputation: 7240
I have a Realm (Swift) object that's existed in my app for about a year now. The model for this object looks like this:
class ChatMessage: Object {
@objc dynamic var messageId: Int = generateId()
// other properties omitted
override static func primaryKey() -> String? {
return "messageId"
}
}
Now, I find myself needing to effectively rename the "messageId" property to "id" and make "id" the primary key. I need to do this because I need this object to conform to a particular protocol (from a framework that I don't control) and that protocol specifies that I need a "messageId" property of type String. Renaming seems to be the most straight forward explanation for what I'm trying to do but I realize that this might also be explained by saying that I want to:
In effect, what I want the object to look like after the change is:
class ChatMessage: Object {
@objc dynamic var id: Int = generateId()
// other properties omitted
override static func primaryKey() -> String? {
return "id"
}
}
I have a migration block defined and I've tried a few different ways of accomplishing this but so far haven't had any luck. Without the migration block, I get the following in the Xcode debug console:
ERROR - Failed to open Realm! Error Domain=io.realm Code=10 "Migration is required due to the following errors:
- Property 'ChatMessage.messageId' has been removed.
- Property 'ChatMessage.id' has been added.
- Primary Key for class 'ChatMessage' has changed from 'messageId' to 'id'.
For what it's worth, I'm using Realm 5.50 and I've read through the docs at https://realm.io/docs/swift/latest/ and I see this statement:
Once an object with a primary key is added to a Realm, the primary key cannot be changed.
That makes it sound like this isn't possible to do with Realm anymore but I'm wondering if anyone can confirm that or if there is, in fact, a way to achieve this? Thanks!
Upvotes: 0
Views: 1640
Reputation: 323
One day someone will come looking for this in flutter:
The simple answer is to use the annotation @MapTo("_id")
class _Car {
@PrimaryKey()
@MapTo("_id")
late ObjectId id;
...
}
Upvotes: 0
Reputation: 35648
You can actually change the primary key within a migration block. Suppose you have a object that looks like this, with 'localID' being the primary key
class TestClass: Object {
@objc dynamic var localID = UUID().uuidString
override static func primaryKey() -> String? {
return "localID"
}
}
and we want to change the primary key to _id
. The migration block would look something like this
let vers = UInt64(3)
let config = Realm.Configuration( schemaVersion: vers, migrationBlock: { migration, oldSchemaVersion in
print("oldSchemaVersion: \(oldSchemaVersion)")
if (oldSchemaVersion < vers) {
print(" performing migration")
migration.enumerateObjects(ofType: TestClass.className()) { oldItem, newItem in
let oldId = oldItem!["localID"]
newItem!["_id"] = oldId
}
}
})
I would suggest using _id
instead of id
so it will be compatible with MongoDB Realm in the future. See Define a Realm Schema
Upvotes: 2