ObjectID error with .object(ofType: forPrimaryKey:) function?

I am suddenly getting an error when trying to get a specific object from Realm via it’s primary ObjectId key. This may be something I am overlooking or a change I was not aware of so wanted to put it out there.

Here’s the error

Invalid value ‘60574941858a6fbe9a7fff6e’ of type ‘Swift.__SharedStringStorage’ for ‘object id’ property ‘DogClass._id’.

And my DogClass

class DogClass: Object {
    @objc dynamic var _id = ObjectId.generate()
    @objc dynamic var name = ""

    override static func primaryKey() -> String? {
        return "_id"
    }
}

and the code that causes the crash

let existingDog = realm.object(ofType: DogClass.self, forPrimaryKey: "60574941858a6fbe9a7fff6e")

I could have sworn this was working previously; the only change I made was updating to RealmSwift 10.7.2

This is a local only, non-sync’d Realm, macOS 11.2.3, Realm 10.7.2, XCode 12.4

Edit

I just noticed a similar question over in the MongoDB Realm forum

But is that solution the solution? Seems strange we’re forced to use StaticString as in

let ss: StaticString = "60574941858a6fbe9a7fff6e"
let theKey = ObjectId(ss)
let existingDog = realm.object(ofType: DogClass.self, forPrimaryKey: theKey)

let existingDog = realm.object(ofType: DogClass.self, forPrimaryKey: ObjectId(string : "60574941858a6fbe9a7fff6e"))

@Muhammad_Awais

Thank you but isn’t that the same code posted in my question? theKey is an ObjectId with a static string.

no check primary lkey passed as objectId

@Muhammad_Awais

That code won’t work because ObjectId(string: can throw as shown in the documentation for ObjectId

Declaration
SWIFT
public override required init(string: String) throws

So it would need to include a try

let ss = try! ObjectId(string: "60574941858a6fbe9a7fff6e")

or as I mentioned, a StaticString. So this for example generates a compiler error

    let regularString = "6058ed1016f023a5a8dca06a"
    let objIdString = ObjectId(regularString)

Cannot convert value of type ‘String’ to expected argument type ‘StaticString’

Hopefully one of the Realm’ers can clarify how to implement this or what I am missing. Let me re-state the question

How to pass an ObjectId into the primaryKey property of the function .object(ofType: forPrimaryKey:)

A static string is useless because it would have to be hard coded (hence: static).

ObjectId(string: "60574941858a6fbe9a7fff6e") can throw because the string you provide may not be of the required length or may contain character outside of the 0..e range.

This code should work:

do {
  try let id = ObjectId(string: yourString)
  let existingDog = realm.object(ofType: DogClass.self, forPrimaryKey: id)
} catch {
   // Do something to react to the error
}

@Andrew_Morgan

Thanks for the answer.

Was that a recent change? We have existing code in a project that has not been updated in a while where that was not required e.g. forPrimaryKey: some string.

Do you know with what SDK version that change was made?

I have it working in a current project but that should really be in the documentation so it’s clear this

let existingDog = realm.object(ofType: DogClass.self, forPrimaryKey: "xxxyyzzz")

is only applicable to non-sync’d realms that do NOT use ObjectID to generate primary keys.

Primary Keys

I’m afraid that I don’t know – I’ve always explicitly converted the string to an ObjectId before trying to match with an ObjectId field.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.