Delete objects from List in Realm - Swift

JEL picture JEL · Mar 20, 2017 · Viewed 14.6k times · Source

I have a collection view where you can select multiple cells to delete. This means that if multiple cells are deleted, then multiple objects should also be deleted in Realm - 1 object per cell.

I have a function which takes an array of Int's which will be populated from the selected indexPaths of the collection view.

The problem is that I'm not sure how to do both
1) Delete the objects in Realm and
2) Have the List up to date without the deleted objects

My code is:

I get the index paths like so:

let indexPaths = collectionView.indexPathsForSelectedItems

This is my function to take in the indexPaths, update the List, and delete the objects in Realm. It is currently not working because the objects are not being deleted. I noticed that removeAll does not delete anything.

func removeVideos(at indexes: [Int]) {
        let newVideos = List<Video>()
        for (index, video) in favorite!.videos.enumerated() {
            if !indexes.contains(index) {
                newVideos.append(video)
            }
        }

        let realm = try! Realm()
        try! realm.write {
            favorite!.videos.removeAll()

            newVideos.forEach { newVideo in
                favorite!.videos.append(newVideo)
            }
        }
    }

I call that function like so:

removeVideos(at: indexPaths.map { $0.item })

Any thoughts?

Answer

TiM picture TiM · Mar 21, 2017

List.removeAll() doesn't delete the objects from Realm. It just removes them out of that List object, deleting their relationship to their parent object (in this case, the favorite object). Deleting objects along with their parent List object is a feature called 'cascading deletes' and it's still being discussed on the Realm GitHub.

If you actually want to delete them, then simply call realm.delete(favorite!.videos). This will delete them from Realm and automatically clear out the List property.

You might need to be careful with your implementation there though. Once an Object has been deleted from Realm, any existing references to it cannot be re-added back into Realm. It may just be appropriate to just delete the newVideo objects themselves instead of cleaning out the whole List.

func removeVideos(at indexes: [Int]) {
    let newVideos = [Video]()
    for (index, video) in favorite!.videos.enumerated() {
        if !indexes.contains(index) {
            newVideos.append(video)
        }
    }

    let realm = try! Realm()
    try! realm.write {
        realm.delete(newVideos)
    }
}

As long as you've set a Realm notification block on your collection view, this should be all you need to do for them to be removed from your UI.