Error deleting data from SwiftUI List and Realm

Hi all,

Has anyone been able to successfully integrate Realm with SwiftUI, especially deleting records/rows from a SwiftUI List? I have tried a few different things but no matter what I do I get the same error. After reading some related threads I found out that other people have the same issue.

The following code successfully presents all of the items from Realm in a SwiftUI List, I can create new ones and they show up in the List as expected, my issues is when I try to delete records from the List by either manually pressing a button or by left-swiping to delete the selected row, I get an Index is out of bounds error.

Here is my code:

Realm Model

class Dog: Object {
    @objc dynamic var name = ""
    @objc dynamic var age = 0
    @objc dynamic var createdAt = NSDate()
    
    @objc dynamic var userID = UUID().uuidString
    override static func primaryKey() -> String? {
        return "userID"
    }
}

SwiftUI Code

class BindableResults<Element>: ObservableObject where Element: RealmSwift.RealmCollectionValue {
    var results: Results<Element>
    
    private var token: NotificationToken!
    
    init(results: Results<Element>) {
        self.results = results
        lateInit()
    }
    func lateInit() {
        token = results.observe { [weak self] _ in
            self?.objectWillChange.send()
        }
    }
    deinit {
        token.invalidate()
    }
}

struct DogRow: View {
    var dog = Dog()
    var body: some View {
        HStack {
            Text(dog.name)
            Text("\(dog.age)")
        }
    }
}


struct ContentView : View {

    @ObservedObject var dogs = BindableResults(results: try! Realm().objects(Dog.self))

    var body: some View {
        VStack{
                
        List{
            ForEach(dogs.results, id: \.name) { dog in
                DogRow(dog: dog)
            }.onDelete(perform: deleteRow )
        }
           
            Button(action: {
                try! realm.write {
                    realm.delete(self.dogs.results[0])
                }
            }){
                Text("Delete User")
            }
        }
    }
    
    private func deleteRow(with indexSet: IndexSet){
        indexSet.forEach ({ index in
            try! realm.write {
                realm.delete(self.dogs.results[index])
            }
        })
    }
}

Error

Terminating app due to uncaught exception ‘RLMException’, reason: ‘Index 23 is out of bounds (must be less than 23).’

Of course, the 23 changes depending on how many items are in the Realm database, in this case, I had 24 records when I swiped and tapped the delete button.

1 Like

Hey, I’m currently facing the same issue unfortunately.

Did you ever discover a solution?

If so, could you please share it with me/ this thread?

Best Regards,

Same thread posted on stackoverflow
Please check.You may get some clues

Unfortunately no, I had to stop working on that project and I haven’t dig into it more. Check out the thread from Stackoverflow, it may help you. Thanks.

1 Like

Following this tutorial: https://developer.mongodb.com/article/realm-cocoa-swiftui-combine
and this demo: https://github.com/realm/realm-cocoa/tree/master/examples/ios/swift/ListSwiftUI

shows how to work around this issue using the new frozen objects, at the cost of introducing a new Realm object just to wrap a list. Still hoping to find a solution that would not require this wrapper when I can find the time for it…

1 Like

@nimi What wrapper are you referring to? How would you prefer it to look?

I’m referring to the Recipes object.

The ListSwiftUI demo defines both Recipe (the actual model) and Recipes which just wraps a list of Recipe. The reason for this to my understanding is just to be able to use the model with SwiftUI because List is an ObservableObject and Results is not.

I’d prefer to be able to show a list of Recipe objects in SwiftUI without needing to define and store another Realm object.