Search code examples
swiftdatabasexcoderealmlinkingobjects

Understanding LinkingObjects in Realm Xcode 12, Also when to use it


In Realm, I had problem understanding ( Im new in Realm T,T ) the implementations of LinkingObjects , let's say a Person could have more than one Dog ( List of Dog ) so I would write the code such as below:

Person : Object {
   dynamic var name:String = ""
   let dogs = List<Dog>() 
}

Dog : Object {
   dynamic var name: String = ""
   let walkers = LinkingObjects<fromType: Person.self, property:"dogs"> 
}

lets say

Person A
dogs = [Alex,Cindy]

Person B
dogs = [Doggo,Kiba]

if I delete Alex using Realm.delete then it become Person A dogs = [Cindy] this is quite straight forward.

but when I remove LinkingObjects from the class such as below:

 Person : Object {
   dynamic var name:String = ""
   let dogs = List<Dog>() 
}

Dog : Object {
   dynamic var name: String = ""
}

the app still can run normally without any diff, I can still add Person 3 and append a list of Dog. Also when deleting ( Realm.delete ) there is no difference as when I'm adding LinkingObject to the Dog class. what's the difference here? When can I use LinkinObject? Can anyone please explain? or write some more understandable code?

Already read all the previous answer but still I need another explanation. Thank You So Much!!


Solution

  • You can think of LinkingObjects almost as a computed property - it automagically creates an inverse link to the parent object when the child object is added to the parent objects List.

    So when a Dog is added to a person's dogs list, a person reference is added to the Dog's walkers list. Keeping in mind that it's a many to many relationship so technically if Person A adds Doggo, and Person B adds Doggo, the Doggo's inverse relationship 'walkers' will contain Person A and Person B

    the app still can run normally without any diff

    Which is true, it doesn't affect he operation of the app. HOWEVER the difference is that by removing the walkers LinkingObjects, there's no way to query Dogs for their Person and get Dog Results (i.e. you can't traverse the graph of the relationship back to the person)

    In other words we can query Person for kinds of dog stuff

    let results = realm.objects(Person.self).filter("ANY dogs.color == 'brown'")
    

    which returns a results object contains Persons that have a brown dog. However, we don't know which dog they have is brown; could be one, could be three.

    However, suppose you want to get a results object containing specific brown dogs and want the owners name for each - you can't really do that without an inverse relationship (LinkingObjects)

    let dogResult = realm.object(Dog.self).filter("color == 'brown'")
    for dog in dogResult {
       let person = dog.walkers.first!.name //assume there is only one owner
       print(person.name)
    }
    

    The dogResults will only contain brown dogs, and you know specifically which ones they are.

    So that's a big difference; without LinkingObjects we rely on returning Person objects and then iterating or processing each to get to the data we want. With LinkingObjects we can specifically get the objects we want to work with.

    It's super handy when you want to add an observer to results to watch for changes - say on Brown dogs - to be notified of changes.