Chris
Chris

Reputation: 8020

How to properly handle create and update for realm.io relationships

I've got two RLMObjects:

class Timeline: RLMObject {

    dynamic var entries = RLMArray(objectClassName: Entry.className())
    dynamic var id          = 0
    dynamic var title       = ""
    dynamic var coverPhoto  = ""
    dynamic var body        = ""

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

class Entry: RLMObject {


    dynamic var id          :Int = 0
    dynamic var timelineID  :Int = 0
    dynamic var name        :String = ""
    dynamic var caption     :String = ""
    dynamic var body        :String = ""
    dynamic var imageURL    :String = ""

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

As you can see there is a To-Many relationship between a Timeline and an Entry. A timeline has many Entries.

the JSON fetch and assignment of my timelines works just fine, they are being fetched and set with:

realm.beginWriteTransaction()
Timeline.createOrUpdateInDefaultRealmWithObject(timelineObject)
realm.commitWriteTransaction()

My problem arises when I'm trying to fetch the entries (which is a separate JSON request/response) for a given timeline and set them.

Fetching and creating them like this works just fine:

realm.beginWriteTransaction()
Entry.createOrUpdateInDefaultRealmWithObject(entryObject)
realm.commitWriteTransaction()

But of course that doesn't associate them with my Timeline object. So then I tried to get my Timeline object and then adding the Entry object to my timeline by doing:

let timelineObject = Timeline(forPrimaryKey: id)
timelineObject.entries.addObject(entryObject) 

(inside of a transaction ofc).

This works fine for the initial fetch. But when I try to refetch your data, you get the following RLMException:

'RLMException', reason: 'Can't set primary key property 'id' to existing value 59.'

Am I doing something wrong, or is this a bug? It seems like there should be an instance method on RLMObject that creates or updates a product, like it's class method does?

Solution As segiddins comment suggests, you add the return from the class method: createOrUpdate... and then add that return to your object (in my case, the timelineObject.entries.addObject(entryReturn).

let realm = RLMRealm.defaultRealm()                        
realm.beginWriteTransaction()

for entry in json["entries"] {

...
//Process and map the JSON
...
let entryReturn = Entry.createOrUpdateInDefaultRealmWithObject(entryObject)
timelineObject.entries.addObject(entryReturn)

}
realm.commitWriteTransaction()

Upvotes: 4

Views: 4265

Answers (1)

segiddins
segiddins

Reputation: 4120

Try adding the Entry object that gets returned from the createOrUpdate call.

Upvotes: 5

Related Questions