7

I'm receiving an RLMException for the following reason:

Attempting to create an object of type 'Student' with an existing primary key value '258975085-504336622-62850'.

The confusing part is that it's occurring just after a check that there are no existing objects with this key in the Realm.

let realm = try Realm()
if let info = realm.object(ofType: Student.self, forPrimaryKey: newStudent.userId) {
    try realm.write {
        info.name = newStudent.name
        info.school = newStudent.school
        info.email = newStudent.email
    }
}
else {
    try realm.write {
        realm.add(newStudent) //RLMException occurs here
    }
}

This code is all running asynchronously on the GCD utility queue, inside a do/catch block. It's triggered by a button in the user interface, but nothing else is accessing realm at the same time.

Why could that if statement allow the else code to run?

Kaushik Makwana
  • 1,329
  • 2
  • 14
  • 24
Andy
  • 723
  • 9
  • 24
  • why are you not writing userId to realm for new objects? – iOS Developer Feb 28 '18 at 10:01
  • My userId is part of the Student object, so if it can find one with matching id then it doesn't need to write the id again, and it's included in the model if I'm creating a new object. – Andy Feb 28 '18 at 10:05
  • did you try printing newStudent.userId's value? is it '258975085-504336622-62850'? – iOS Developer Feb 28 '18 at 10:10
  • Yes, that's exactly what it was. I'm more confused by why it wouldn't be returned by the object call for that id at the start – Andy Feb 28 '18 at 10:16

3 Answers3

4
try! self.realm.write {
    self.realm.add(newStudent, update: true)
}

You're adding same Object (student) with existing primary key. So you can just update current one. Instead of deleting and adding new one.

Ignelio
  • 101
  • 11
  • But there are certain different fields that might already be saved. Would I not have to retrieve an object anyway to get those values rather than overwriting them? – Andy Feb 28 '18 at 10:25
  • take a look here : https://stackoverflow.com/questions/32891269/prevent-realm-from-overwriting-a-property-when-updating-an-object – Ignelio Mar 01 '18 at 11:16
4

In my case, I added condition to check whenever new user logs in:

if newStudent == nil{
     self.realm.add(newStudent, update: .all)
}
Abdul Karim Khan
  • 4,256
  • 1
  • 26
  • 30
0

Answering my own question because I found the problem.

I think the problem was a previous app screen trying to save (the same) student object on a queue with Utility quality of service, meaning that it finished saving after the call to realm.object(...), but before the call to realm.add(...).

Moving the if statement inside the realm write transaction also helped (thanks EpicPandaForce).

Andy
  • 723
  • 9
  • 24