I am trying to display some simple Realm objects in a SwiftUI list. Each object also has related child objects.
I am able to display the parent objects just fine by using the @ObservedResults(Parent.self) property wrapper. Simply adding or removing the parent objects to/from Realm updates the list and this works great.
The problem occurs when I want to display the related child models. When I attempt to add the child models in Realm the same way I added the parent models, also using the default Realm.Configuration, I get an RLMException saying Cannot modify managed RLMArray outside of a write transaction.
Here is a simple SwiftUI view that illustrates the problem.
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)
}
}
}
}
}
}
And here are my models:
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
}
}
By clicking the buttons Create parents and Delete all you see the parent models appear and disappear as expected. Clicking Create child produces the error.
I'm really at a loss here, any help with this is much appreciated. Thanks!