Creating a LinkingObjects property in RealmSwift by using multiple-level properties

4.3k Views Asked by At

According to the Realm documentation for v0.102.0, this is how you create an inverse relationship:

Person

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

Dog (v1)

class Dog: Object {
    // ... other property declarations
    let owners = LinkingObjects(fromType: Person.self, property: "dogs")
}

Suppose that we have another class, called DogFood, and we want to create an inverse relationship called buyers that tracks which instances of Person have a Dog that eats that instance of DogFood. We could try the following:

Dog (v2)

class Dog: Object {
    // ... other property declarations
    let favoriteFoods = List<DogFood>
    let owners = LinkingObjects(fromType: Person.self, property: "dogs")
}

DogFood

class DogFood: Object {
    // ... other property declarations
    let buyers = LinkingObjects(fromType: Person.self, property: "dogs.favoriteFoods")
}

However, this throws the following error: Property 'dogs.favoriteFoods' declared as origin of linking objects property 'buyers' does not exist.

Is there another way to achieve the same effect?

1

There are 1 best solutions below

0
catalandres On BEST ANSWER

This can be achieved with a filter, with the caveat that the DogFood object we need to query about needs to be part of a Realm.

The code would go as follows:

class DogFood: Object {
    // ... other property declarations
    var items: Results<Person> {
        if let realm = self.realm {
            return realm.objects(Person).filter(NSPredicate(format: "ANY dogs.favoriteFoods.id == %@", self.id))
        } else {
            return RealmSwift.List<Person>().filter("1 != 1")
        }
    }
}

The property realm is of type Realm? and comes into the picture through inheritance from Object. It points towards the realm that a particular Object instance is in and returns nil if not assigned to one. If that is the case, we force the property items to return an empty set of Results<Person>.