I am quite confused about how lists are saved in a realm.
If I have the following schema:
class First: Object {
@Persisted var children = List<Second>()
convenience init(children: [Second]) {
self.init()
self.children.append(objectsIn: children)
}
}
class Second: Object {
@Persisted var children = List<Third>()
convenience init(children: [Third]) {
self.init()
self.children.append(objectsIn: children)
}
}
class Third: Object {
}
If I try to save a First object like this:
let first = First(children: [Second(children : [Third()])])
let realm = try! Realm()
realm.write {
realm.add(first, update: .modified)
}
The children Second objects are not saved. What I have to do is this:
let first = First(children: [Second(children: [Third()])])
let realm = try! Realm()
let children = first.children
try! realm.write {
realm.add(children, update: .modified)
realm.add(first, update:.modified)
first.children.append(objectsIn: children)
}
`
and what is even more odd is that the children of the Second objects are save to the realm successfully.
Am I missing something here, or am I doing something wrong?
HI @Nathan_Mann, thank you for using the Swift SDK.
I believe it is because of the 2 levels of arrays of embedded objects. If the Second class did not have the children array of objects, or if it was an array of primitives (e.g. String, int, etc.) then I think it should be saved successfully.
I have reached out to the Swift SDK team to confirm.
Well it does and doesn’t. In this case it needs a primary key because of how realm is being written to. Primary keys are required* if you want to update an object BY that primary key - that’s called an upsert
To upsert an object, call Realm.add(_:update:) with the second parameter, update policy, set to .modified . Upserts require the data model to have a primary key.
On the other hand, if you just want to create the object(s) and not use a primary key, then change the write code
try! realm.write {
realm.add(first)
}
On a somewhat unrelated note, List is actually a naming collision with SwiftUI List. So it’s probably a good idea to name your list properties with that
@Persisted var children = RealmSwift.List<Second>()
So - in a nutshell, if you take your code and add a property of any kind to Third, and then write to realm per above, it works perfectly.