我有一个对象有许多狗的人.应用程序有单独的页面,它只显示狗和其他页面显示人的狗
我的模型如下
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) } }