'RLMException: 'Primary key property 'serial' does not exist on object 'Book' Migrating to Swift 4

I'm running into this issue with Realm on iOS using Swift 4 compilation, where on startup the app crashes with the following message

RLMException', reason: 'Primary key property 'serial' does not exist on object 'Book''

I saw similar error messages, but not the same one. This is what my object looks like

import Foundation
import RealmSwift

class Book: Object {
    dynamic var serial: String = ""
    dynamic var title: String = ""
    dynamic var pages: Int = 0
    dynamic var genre: String = ""

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

When I checked the default.realm file through the Realm Browser app, I noticed that the entries only have a # (0,1,2) and no data in it. If I comment out the primary key, it runs, but nothing is stored in Realm for this object. Can't figure out why it's crashing!



Solution 1:[1]

In Realm, the properties of your model have to have the @objc dynamic var attribute, that is what I was missing.

From Realm website:

Realm model properties must have the @objc dynamic var attribute to become accessors for the underlying database data. Note that if the class is declared as @objcMembers (Swift 4 or later), the individual properties can just be declared as dynamic var.

Solution 2:[2]

Although it doesn't necessarily about migration, there's an issue with iOS 13 and Xcode 11 which may cause this problem. All String properties of Realm classes with a default String value set are disregarded somehow. You can fix this by updating to the latest version (currently 3.20.0) and than on Xcode: Product -> Clean Build Folder.

If you're using cocoa-pods, do this:

Open your project's Podfile, and replace RealmSwift line with:

pod 'RealmSwift', '~> 3.20.0'

Then, open terminal on the project's folder and:

pod repo update
pod install

Hope that helps.

Solution 3:[3]

import Foundation
import RealmSwift

class Book: Object {
   @objc dynamic var id : Int = 0
   @objc dynamic var serial: String = ""
   @objc dynamic var title: String = ""
   @objc dynamic var pages: Int = 0
   @objc dynamic var genre: String = ""

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

Solution 4:[4]

I had a similar issue, however mine was due to the fact that I was converting a non-Realm class to a Realm class. I originally had:

@objc dynamic let customerId: String
override static func primaryKey() -> String? {
    return "customerId"
}

...but I needed to change the "let" to a "var":

@objc dynamic var customerId: String
override static func primaryKey() -> String? {
    return "customerId"
}

It wasn't obvious from the error message that that was the problem, but it instantly fixed the issue.

Solution 5:[5]

Change Realm in Pod file with the new version of Realm like :

From

pod 'RealmSwift', '~> 3.11.0'

TO

 pod 'Realm',  git: 'https://github.com/realm/realm-cocoa.git', branch: 'master', submodules: true


  pod 'RealmSwift', git: 'https://github.com/realm/realm-cocoa.git', branch: 'master', submodules: true

make sure about the all fields define like :

 @objc dynamic var myID: String!

Solution 6:[6]

In my case, adding @objMembers on top of the class name fixed it

Ex:

@objcMembers
internal final class Recipient: Mappable {
dynamic var transferID: String = ""

Solution 7:[7]

Computed primary keys do not work (like in hijacked id from a an embedded object see code below):

@objc dynamic var id: String
{
    guard let id = header?.id else {
        assertionFailure()
        return ""
    }
    return id
}

So you have to make a plain @Persisted var id: String set in in init()s of all ilk and presumably keep track of the one2one dependency (header in my case that has the key) with didSet. Realm object observer realm swift: how could I trap on object being invalidated?. might be of some use? didSet should suffice me thinks.

Solution 8:[8]

In same this issue in my case is born I forget write @objc in param

my case error is

dynamic var yourValue: String!

fix by

 @objc dynamic var yourValue: String!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 tomaculum
Solution 2
Solution 3 Khawar Islam
Solution 4 wildcat12
Solution 5
Solution 6 Kiki Sasha
Solution 7
Solution 8 Papon Smc