Search code examples
swiftrealmrlmlinkingobjects

Delete specific object from LinkingObjects list - Realm Swift


I am currently trying out Realm on a test project and I have been struggling with removing a specific object from a List. LensDBObject and ListDBObject. LensDBObject contains a list of lenses and ListDBObject are lists of existing lenses. A lens can be in multiple lists and I'd like to remove a specific lens from a specific list but not remove if from the other lists.

Below are my two classes:

@objcMembers class LensDBObject: Object {

   dynamic var id = UUID().uuidString
   dynamic var manufacturer = ""
   dynamic var series = ""
   dynamic var serial = ""
   dynamic var isSelected = false

   override static func primaryKey() -> String? {
       return "id"
   }

   let objects = LinkingObjects(fromType: ListDBObject.self, property: "lensList")

}

@objcMembers class ListDBObject: Object {
   dynamic var listName = ""
   let lensList = List<LensDBObject>()

}

Below is my code to find a specific lens in the list I want. The values returned are what I expect.

let listToSearch = realm.objects(ListDBObject.self).filter("listName == %@", "List 542")
print(listToSearch)
let filteredResults = listToSearch[0].lensList.filter("manufacturer == %@ AND series == %@ AND serial == %@", "Panavision" , "Primo Prime", "407")
print(filteredResults)

However, when I try to delete filteredResults, it deletes it from the lensDBOject altogether. I just want to be able to delete this specific lens from this specific list.

try! realm.write {
    realm.delete(filteredResults)
}

I tried using for loops to get the index of the lens in the list and then delete it directly from that. But it still deletes the lens everywhere.

Am I missing something? Should I be using a one-to-many relationship as opposed to a LinkingObject?

Thanks for you help!


Solution

  • Try something like this. You only want to remove the lens from the list, not delete it from the Realm.

    try! realm.write {
        filteredResults.forEach { lens in
            if let index = listToSearch[0].lensList.index(of: lens) {
                listToSearch[0].lensList.remove(at: index)
            }
        }
    }
    

    Note that this will remove from that one specific list all lenses that match your filter.

    Edit: Updated to reflect Realm's custom List class.

    The if let is required, because index(of:) could potentially return nil if the object is not found in the list. Additionally, we must do it one item at a time rather than getting all the indexes first, since removing an item would cause the index array to be wrong.