44

I'm using Realm in a new iOS Swift project. I'm using Xcode 6.0.1 with iOS SDK 8.0 and Realm 0.85.0

I'm trying to use the new Realm primary key feature so I can do an addOrUpdateObject.

Here is a sample model:

import Foundation
import Realm

class Foo: RLMObject {
    dynamic var id = 0
    dynamic var title = ""

    func primaryKey() -> Int {
        return id
    }
}

And how I'm trying to add/update a new object:

let foo = Foo()
foo.title = titleField.text
foo.id = 1

// Get the default Realm
let realm = RLMRealm.defaultRealm()

// Add to the Realm inside a transaction
realm.beginWriteTransaction()
realm.addOrUpdateObject(foo)
realm.commitWriteTransaction()

I get this error:

RLMExecption', reason: ''Foo' does not have a primary key and can not be updated

Here are the docs on the primary key. I'm probably not setting it correctly: http://realm.io/docs/cocoa/0.85.0/api/Classes/RLMObject.html#//api/name/primaryKey

Latest docs are here now: https://realm.io/docs/objc/latest/api/Classes/RLMObject.html#//api/name/primaryKey

Idan
  • 5,405
  • 7
  • 35
  • 52
jeffjv
  • 3,461
  • 2
  • 21
  • 28
  • 1
    broken link to the realm.io doc – Tyler Aug 17 '15 at 16:54
  • We've moved our "cocoa" docs to "objc" when we launched Realm Swift, so try this link instead: https://realm.io/docs/objc/latest/api/Classes/RLMObject.html#//api/name/primaryKey We're setting up redirects from old links so this doesn't cause as much confusion in the future. – jpsim Aug 21 '15 at 15:52
  • The redirect from the old links to the new docs doesn't seem to be working so I updated my question with the new link. – jeffjv Dec 03 '15 at 06:36

4 Answers4

93

As of Realm Swift v10.10.0, you declare a primary key with @Persisted(primaryKey: true):

class Foo: Object {
    @Persisted(primaryKey: true) var id = 0
    @Persisted var title = ""
}

Older versions:

primaryKey needs to be a class function which returns the name of the property which is the primary key, not an instance method which returns the value of the primary key.

@objcMembers class Foo: RLMObject {
    dynamic var id = 0
    dynamic var title = ""

    override class func primaryKey() -> String? {
        return "id"
    }
}
Thomas Goyne
  • 8,010
  • 32
  • 30
  • Thanks, yes these were my problems. Also, to get it working I to add 'override' to override the declaration. – jeffjv Oct 02 '14 at 00:50
  • I've updated the answer to include the "override" keyword needed for Realm to correctly call the custom class function – Glen Selle Oct 09 '14 at 21:06
  • For some reason I get an "invalid redeclaration of 'primaryKey()'" error. Can't seem to figure out why. – Entalpi Jan 17 '15 at 12:00
  • 1
    @Entalpi I updated the docs http://realm.io/docs/cocoa/0.89.2/#customizing-models, are you still seeing any errors? Feel free to message on https://groups.google.com/forum/#!forum/realm-cocoa if you are, w/ a sample of your code – yoshyosh Jan 20 '15 at 18:28
  • Per @CherryKuczery, the return type is optional. If I had enough reputation, I'd just merge the two answers. – clozach Mar 27 '16 at 23:49
8

The return type of primaryKey() is optional:

class Foo: RLMObject {
    dynamic var id = 0
    dynamic var title = ""

    override class func primaryKey() -> String? {
        return "id"
    }
}
CherryKuczery
  • 163
  • 2
  • 7
8

For Swift 5:

import RealmSwift

     class Signature: Object {

           @objc dynamic var id = ""

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

To avoid: Terminating app due to uncaught exception 'RLMException', reason: 'Primary key property 'id' does not exist on object.

Maria Ortega
  • 371
  • 4
  • 8
1

Realm 10.12.0 & Swift 5

Legacy property declarations using @objc:

import RealmSwift

class Signature: Object {
    @objc dynamic var id = ""

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

When using @Persisted, use @Persisted(primaryKey: true) instead:

import Foundation
import RealmSwift

class MyModel: Object {
    @Persisted var pan: String?
    @Persisted var exp: String?
    @Persisted var cvv: String?
    @Persisted(primaryKey: true) var myId: String?
    
    override init() {}
    
    init(pan: String, exp: String, cvv2: String) {
        super.init()
        self.pan = pan
        self.exp = exp
        self.cvv = cvv2
    }
}
Mahdi Moqadasi
  • 2,029
  • 4
  • 26
  • 52