【问题标题】:Append existing object to Realm List将现有对象附加到领域列表
【发布时间】:2016-08-05 13:03:54
【问题描述】:

我的代码中有带有主键的 CatalogItem 对象。 Realm 在写入以下代码时抛出错误:

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)
        }
    }
}

错误:

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

我希望 Realm 引用现有的 CatalogItem,但看起来它正在尝试添加另一个。 有没有办法实现这种关系? 注意:所有对象都存储在一个领域中。

【问题讨论】:

  • 好吧,我不是在创建另一个对象,而是引用现有对象。我的意思是,CartItem 根本没有主键。只有它引用的元素 - CatalogItem 有一个。但是我没有在任何地方打电话给CatalogItem.init(),那为什么又要创建它呢?
  • 是的,你是对的,它不是一个 dup,但答案几乎是一样的,你不能有两个具有相同主键的对象
  • 让我提出这样的问题:当我创建CartItem并将CatalogItem传递给它时,Realm会尝试创建另一个CatalogItem吗?
  • 好的,现在我从我的应用程序的另一个地方打电话给addItem(),一切正常,看起来问题出在其他地方。

标签: ios swift realm


【解决方案1】:

如果您将非托管领域对象附加到托管List,则将创建该非托管对象。但是,使用现有主键创建对象是错误的。您可以使用Realm.add(_:update: true) 指定如果对象不存在则创建该对象,否则使用您传入的新值更新现有对象的属性。

所以我认为你希望你的 addItem() 函数看起来像这样:

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)
    }
}

【讨论】:

  • 谢谢!那正是我的问题,但我必须以不同的方式解决它。
【解决方案2】:

正如 jpsim 所指出的,问题是我尝试将非托管对象附加到领域,并且数据库中有一个具有相同主键的对象。 我必须以不同的方式解决问题,因为建议的解决方案会删除领域中存在的对象的属性。

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)
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-19
    • 1970-01-01
    相关资源
    最近更新 更多