具有父模型和子模型的 RealmSwift @ObservedResults,不能在写入事务之外修改托管 RLMArray

RealmSwift @ObservedResults with parent and child models, cannot modify managed RLMArray outside of a write transaction

我正在尝试在 SwiftUI 列表中显示一些简单的 Realm 对象。每个对象还有相关的子对象。

我可以使用 @ObservedResults(Parent.self) 属性 包装器很好地显示父对象。简单地添加或删除父对象 to/from Realm 更新列表,效果很好。

当我想显示相关的子模型时出现问题。当我尝试以与添加父模型相同的方式在 Realm 中添加子模型时,也使用默认 Realm.Configuration,我得到一个 RLMExceptionCannot modify managed RLMArray outside of a write transaction.

这是一个简单的 SwiftUI 视图,可以说明问题。

struct ContentView: View {    
    
    @ObservedResults(Parent.self) var parents
    
    var body: some View {
        VStack(spacing: 15) {
            Button("Create parents") {
                let realm = try! Realm()
                try! realm.write {
                    realm.add(Parent(id: 1, name: "Nick"), update: .all)
                    realm.add(Parent(id: 2, name: "Lucas"), update: .all)
                    realm.add(Parent(id: 3, name: "Ryan"), update: .all)
                }
            }
            Button("Create child") {
                guard let parent = parents.first else {
                    return
                }
                let realm = try! Realm()
                try! realm.write {
                    let child = Child(id: parent.children.count + 1, name: "Foo")
                    parent.children.append(child)
                }
            }
            Button("Delete all") {
                let realm = try! Realm()
                try! realm.write {
                    realm.deleteAll()
                }
            }
            List(parents) { parent in
                VStack {
                    Text(parent.name)
                    ForEach(parent.children){ child in
                        Text("Child: \(child.name)")
                            .padding(.leading, 10)
                    }
                }
            }
        }
    }
}

这是我的模型:

class Parent: Object, ObjectKeyIdentifiable {
    
    @objc dynamic var id: Int = 0
    @objc dynamic var name: String = ""
    
    var children = List<Child>()
    
    override class func primaryKey() -> String? {
        return "id"
    }
 
    convenience init(id: Int, name: String) {
        self.init()
        self.id = id
        self.name = name
    }
}

class Child: Object, ObjectKeyIdentifiable {
    
    @objc dynamic var id: Int = 0
    @objc dynamic var name: String = ""
    
    private let parents = LinkingObjects(fromType: Parent.self, property: "children")
        
    override class func primaryKey() -> String? {
        return "id"
    }
    
    convenience init(id: Int, name: String) {
        self.init()
        self.id = id
        self.name = name
    }
}

通过单击按钮 Create parentsDelete all,您会看到父模型按预期出现和消失。单击 Create child 会产生错误。

我真的在这里不知所措,非常感谢任何帮助。谢谢!

回答我自己的问题。在将任何子项附加到它之前,您似乎必须 thaw 父模型(无论那意味着什么)。我在任何地方的文档中都找不到这个,所以它可能是一个错误。

无论如何,这是解决方法:

Button("Create child") {
    guard let parent = parents.first?.thaw() else {
        return
    }
    let realm = try! Realm()
    try! realm.write {
        let child = Child(id: parent.children.count + 1, name: "Foo")
        parent.children.append(child)
    }
}