18

我有一个对象有很多狗的人。应用程序有单独的页面,它只显示狗和其他页面,它显示人的狗

我的模型如下

class Person: Object {
    dynamic var id = 0
    let dogs= List<Dog>()

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

class Dog: Object {
    dynamic var id = 0
    dynamic var name = ""

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

我将人员存储在 Realm 中。人有详细信息页面,我们可以在其中获取并展示他的狗。如果狗已经存在,我会更新该狗的最新信息并将其添加到人的狗列表中,否则创建新狗,保存并将其添加到人员列表中。这适用于核心数据。

// Fetch and parse dogs
if let person = realm.objects(Person.self).filter("id =\(personID)").first {
    for (_, dict): (String, JSON) in response {
        // Create dog using the dict info,my custom init method
        if let dog = Dog(dict: dict) {
            try! realm.write {
                // save it to realm
                realm.create(Dog, value:dog, update: true)
                // append dog to person
                person.dogs.append(dog)
            }
        }
    }
    try! realm.write {
        // save person
        realm.create(Person.self, value: person, update: true)
    }
}

在尝试用他的狗更新人时,领域抛出异常 无法创建具有现有主键值的对象

4

2 回答 2

34

这里的问题是,即使您正在创建一个全新的 RealmDog对象,您实际上并没有将该对象持久保存到数据库中,因此当您调用 时append,您正在尝试添加第二个副本。

当您调用 时realm.create(Dog.self, value:dog, update: true),如果具有该 ID 的对象已存在于数据库中,您只需使用dog您创建的实例中的值更新该现有对象,但该dog实例仍然是一个独立副本;它不是Dog数据库中的对象。dog.realm您可以通过检查是否等于来确认这一点nil

因此,当您调用 时person.dogs.append(dog),因为dog不在数据库中,Realm 会尝试创建一个全新的数据库条目,但由于已经有具有该 ID 的狗而失败。

如果您想将该dog对象附加到 a person,则有必要查询 Realm 以检索dog引用数据库中条目的正确对象。值得庆幸的是,这对于由主键支持的 Realm 对象非常容易,因为您可以使用以下Realm.object(ofType:forPrimaryKey:)方法:

if let person = realm.object(ofType: Person.self, forPrimaryKey: "id") {
    for (_, dict): (String, JSON) in response {
        //Create dog using the dict info,my custom init method
        if let dog = Dog(dict: dict)
        {
            try! realm.write {
                //save it to realm
                realm.create(Dog.self, value: dog, update: true)
                //get the dog reference from the database
                let realmDog = realm.object(ofType: Dog.self, forPrimaryKey: "id")
                //append dog to person
                person.dogs.append(realmDog)
            }
        }
    }
    try! realm.write {
        //save person
        realm.create(person .self, value: collection, update: true)
    }
}
于 2016-11-14T18:30:38.370 回答
6

我们不再需要 TiM 的方法了。

使用add(_:update:).

try realm.write {
    realm.add(objects, update: Realm.UpdatePolicy.modified)
    // OR
    realm.add(object, update: .modified)
}

Realm.UpdatePolicy 枚举:

error (default)
modified //Overwrite only properties in the existing object which are different from the new values.
all //Overwrite all properties in the existing object with the new values, even if they have not changed

注意:适用于 Realm Swift 3.16.1

于 2019-06-11T09:10:02.180 回答