领域iOS-如何更新列表?

领域iOS-如何更新列表?,ios,realm,realm-list,Ios,Realm,Realm List,我正在iOS上使用领域的Codable,并发现更新领域中保存的现有记录存在问题。数据由项目列表组成,其中每个项目都有类别列表,每个类别都有描述 这就是我的领域可编码模型的样子 class Items: Object, Decodable { @objc dynamic var id: String = "" @objc dynamic var name: String = "" let categories = List<Categories>()

我正在iOS上使用领域的Codable,并发现更新领域中保存的现有记录存在问题。数据由项目列表组成,其中每个项目都有类别列表,每个类别都有描述

这就是我的领域可编码模型的样子

class Items: Object, Decodable {

    @objc dynamic var id: String = ""
    @objc dynamic var name: String = ""
    let categories =  List<Categories>()
    @objc dynamic var desc: Desc?

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

    var hasSubCategories: Bool {
        if self.categories.count > 0 {
            return true
        }
        return false
    }

    enum CodingKeys: String, CodingKey {
        case id
        case name
        case desc
        case categories
    }

    required init() {
        super.init()
    }

    required init(from decoder: Decoder) throws {

        let container = try decoder.container(keyedBy: CodingKeys.self)

        id = try container.decode(String.self, forKey: .id)
        name = try container.decode(String.self, forKey: .name)
        desc = try (container.decodeIfPresent(Desc, forKey: .desc))
        let categoriesList = try container.decodeIfPresent(List<Categories>.self, forKey: .categories) ?? List<Categories>()
        categories.append(objectsIn: categoriesList)
        super.init()
    }
}

class Categories: Object, Decodable {

    @objc dynamic var id: String = ""
    @objc dynamic var name: String = ""
    @objc dynamic var desc: Desc?
    let categories =  List<Categories>()

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

    var hasSubCategories: Bool {
        if categories.count > 0 {
            return true
        }
        return false
    }

    enum CodingKeys: String, CodingKey {
        case id
        case name
        case categories
   }

    required init() {
        super.init()
    }

    required init(from decoder: Decoder) throws {

        let container = try decoder.container(keyedBy: CodingKeys.self)

        id = try container.decode(String.self, forKey: .id)
        name = try container.decode(String.self, forKey: .name)
        desc = try (container.decodeIfPresent(Desc, forKey: . desc))
        let categoriesList = try container.decodeIfPresent(List<Categories>.self, forKey: .categories) ?? List<Categories>()
        categories.append(objectsIn: categoriesList)
        super.init()
    }
}
当从API接收到已经保存在DB中的数据时,我需要更新它。据我所知,primarykey已实施

realm?.add(Item, update: .modified)
将更新具有相同主记录的现有记录。 已更新具有类项的对象的属性,但未更新类别列表

我试图获取保存在数据库中的现有类别列表,并通过调用
savedItem.categories.removeAll()
修改了与savedItem关联的categories对象,并使用
savedItem.categories.append(objectsIn:itemFromAPI.categories)
当我用

realm?.add(Item, update: .modified)
领域崩溃引发异常-“RLMEException原因:尝试创建具有现有主键值的类型的对象”

所以我试着用

realm?.delete(Category)
然后添加了与项目关联的已修改类别,该操作正在运行

我将类别嵌套到多个级别,并通过再次获取、删除和重新读取来更新它们,这证明是一种痛苦。这就是域中更新记录的工作方式吗

我可以通过简单地为项目分配新对象并使用

realm?.add(Item, update: .modified) 
要像添加新项目一样更新记录吗


任何回复都将不胜感激。

根据评论,问题是

我的问题是如何使用更新域列表属性 realm?.add(项,更新:。已修改)函数

为了清楚起见,让我重申这个问题

如何更新存储在另一个对象列表属性中的对象 列表中存储的对象具有主键

简单的回答是:列表对象包含对该列表中其他对象的引用。因为它包含引用,所以列表本身不需要更新,只需要更新它引用的对象

长期的答案是通过一个例子:让我们来看看一个有狗属性的人

class PersonClass: Object {
   @objc dynamic var person_id = UUID().uuidString
   let dogs = List<DogClass>()

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

class DogClass: Object {
   @objc dynamic var dog_id = NSUUID().uuidString
   @objc dynamic var dog_name = ""

   override static func primaryKey() -> String? {
        return "dog_id"
    }
}
所以现在这个人有两只狗;点点和罗孚

假设我们想把流浪者的名字改成莱西。无需更改或更新人员列表-只需更新领域中的dogs name属性,确保使用相同的dog_id,并且该更改将反映在人员列表中

let updatedDog = DogClass()
updatedDog.dog_id = "the dogs primary key"
updatedDog.dog_name = "Lassie"

try! realm.write {
   realm.add(updatedDog, update: .modified)
}

我认为您在这里要问的是如何使领域列表属性可编码,对吗?如果是这样的话,这已经被问了好几次了。请参见和。检查这些,看看它们是否有帮助,因为列表对象不能直接编码或解码。我的问题是如何使用Realm?.add(Item,update:.modified)函数更新领域列表属性。它似乎没有更新列表属性。我应该获取现有的数据库条目,然后删除条目,使用相同的primarykey创建新条目进行更新,还是可以简单地构建包含新值列表的主对象,并使用设置了更新标志的realm add函数进行更新?我想我有一个答案。如果需要澄清,请告诉我。谢谢Jay向我解释。由于我将Swift Codable与Realm一起使用,所以我的优势是将所有内容解析并整合到保存列表的父类对象中。我想知道是否可以使用这种方法来更新父对象以及与父对象相关联的子列表,就像我在向realmdb插入新对象时所做的那样。根据你的例子,当狗的信息改变时,我得到了完整的人记录和狗的数据。按照您的方法,我将不得不更新个人数据并获取相关的狗列表,然后循环通过单个狗来更新它。@Prabhu经常多次使用Codable,这比它的价值要麻烦得多。一个很好的用例是,如果您将直接JSON导入Swift对象,那么Realm不是Swift——它由ObjC代码和对象支持,您可能会发现最好使用映射到对象属性的初始值设定项代码创建对象。
let person = PersonClass()

let dog0 = DogClass()
dog0.dog_name = "Spot"
let dog1 = DogClass()
dog1.dog_name = "Rover"

person.dogs.append(objectsIn: [dog0, dog1])

try! realm.write {
    realm.add(person)
}
let updatedDog = DogClass()
updatedDog.dog_id = "the dogs primary key"
updatedDog.dog_name = "Lassie"

try! realm.write {
   realm.add(updatedDog, update: .modified)
}