我有一个对象有许多狗的人.应用程序有单独的页面,它只显示狗和其他页面显示人的狗
我的模型如下
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中.人有详细页面,我们取,并显示他的狗.如果狗已经存在,我会更新该狗的最新信息并将其添加到人的狗列表中,否则创建新狗,保存并将其添加到人员列表中.这适用于coredata.
// 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)
}
}
在尝试用他的狗更新人时,领域会抛出异常
无法使用现有主键值创建对象
解决方法
这里的问题是,即使你正在创建一个全新的Realm Dog对象,你实际上并没有将它保存到数据库中,所以当你调用append时,你正试图添加第二个副本.
当你调用realm.create(Dog,value:dog,update:true)时,如果数据库中已存在具有该ID的对象,则只需使用您创建的dog实例中的值更新现有对象,但是那个狗实例仍然是一个独立的副本;它不是数据库中的Dog对象.您可以通过检查dog.realm是否等于nil来确认这一点.
所以当你调用person.dogs.append(dog)时,因为dog还没有在数据库中,所以Realm会尝试创建一个全新的数据库条目,但是因为已经有一个带有该ID的狗而失败了.
如果要将该狗对象附加到某个人,则需要查询Realm以检索引用数据库中条目的正确狗对象.值得庆幸的是,使用主键支持的Realm对象非常简单,因为您可以使用Realm.object(ofType:forPrimaryKey :)方法:
if let person = realm.object(ofType: Person.self,forPrimaryKey: "id") {
for (_,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)
//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)
}
}