Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Append existing object to Realm List

Tags:

ios

swift

realm

I have CatalogItem objects with primary key in my code. Realm is throwing an error during write in the following code:

class CartItem: Object {
    dynamic var id: Int = 0
    dynamic var item: CatalogItem!
    dynamic var amount: Int = 0

    convenience required init(id: Int, item: CatalogItem, amount: Int) {
        self.init()
        self.id = id
        self.item = item
        self.amount = amount
    }
}

class Cart: Object {

    var items = List<CartItem>()

    func addItem(item: CatalogItem) {
        let realm = try! Realm()
        let newItem = CartItem(id: item.id, item: item, amount: 1)
        do {
            try realm.write {
                items.append(newItem)
            }
        } catch let e {
            handleError(e)
        }
    }
}

Error:

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

I expect Realm to reference existing CatalogItem but it looks like it's trying to add another one. Is there a way to implement this kind of relationship? Note: all objects are stored in one realm.

like image 229
charlag Avatar asked Aug 05 '16 13:08

charlag


2 Answers

If you append an unmanaged Realm object to a managed List, that unmanaged object will be created. However, it's an error to create an object with an existing primary key. You can use Realm.add(_:update: true) to specify that you want to create the object if it doesn't exist, otherwise to update the existing object's properties with the new values you're passing in.

So I think you want your addItem() function to look like this:

func addItem(item: CatalogItem) {
    let realm = try! Realm()
    let newItem = CartItem(id: item.id, item: item, amount: 1)
    do {
        try realm.write {
            realm.add(newItem, update: true)
            items.append(newItem)
        }
    } catch let e {
        handleError(e)
    }
}
like image 146
jpsim Avatar answered Nov 06 '22 18:11

jpsim


As jpsim noted, the problem is that I try to append unmanaged object to Realm and there is an object with the same primary key in the database. I had to solve the problem differently because the proposed solution would erase properties of the object that exists in the realm.

func addItem(item: CatalogItem) {
    let realm = try! Realm()
    var catalogItem = item
    if item.realm == nil,
        let foundItem = realm.objects(CatalogItem)
            .filter("id == %@", item.id).first {
        catalogItem = foundItem
    }
    let newItem = CartItem(id: item.id, item: catalogItem, amount: 1)
    do {
        try realm.write {
            items.append(newItem)
        }
    } catch let e {
        handleError(e)
    }
}
like image 21
charlag Avatar answered Nov 06 '22 18:11

charlag