Search code examples
swiftrealm

Why does Realm suggest that List<T> properties be declared using "let"?


Realm's documentation on to-many relationships declares its List<Dog> property using let:

class Person: Object {
    // ... other property declarations
    let dogs = List<Dog>()
}

Why is this List<T> property declared using let when other Realm property types are declared using dynamic var?


Solution

  • List<T> properties should be declared using let as Realm is unable to intercept assignment to these properties. Assigning to List<T> properties won't result in your changes being persisted to the Realm file. By declaring the property using let rather than var you enlist the Swift compiler to detect code that won't do what you intend.

    Instead of assigning to List<T> properties you should mutate the existing value of the property via the methods that are part of the RangeReplaceableCollection protocol to which List<T> conforms.

    For instance, to add a new dog:

    person.dogs.append(lassie)
    

    Or to replace the existing dogs:

    person.dogs.replaceSubrange(0..<person.dogs.count, with: [fido, spot])
    

    Why?

    Realm model classes automatically implement getters and setters for your persisted properties that access the underlying database data. In order to provide these getters and setters, your properties must be declared with the dynamic modifier. This modifier asks Swift to dynamically dispatch accesses to the properties via getters and setters rather than directly accessing the member at compile time. The dynamic modifier comes with a significant limitation: it is only supported for types that can be represented in Objective-C. This is because Swift's dynamic dispatch is built on top of the Objective-C runtime. It is this limitation that prevents Realm from intercepting assignments to List<T> properties.