swiftswiftuicombineswiftui-listrealm-database

How can I properly map RealmDB Results objects to SwiftUI Lists?


I am trying to display results of a realmdb query in a SwiftUI list but have trouble when deleting database objects.

I am trying to use something like this:

final class DBData: ObservableObject{

let didChange = PassthroughSubject<DBData, Never>()

private var notificationTokens: [NotificationToken] = []
var events = try! Realm().objects(ADMEvent.self)
@Published var events: [ADMEvent] = []
init() {
    // Observe changes in the underlying model
    self.notificationTokens.append(posts.observe { _ in
        self.events = Array(self.posts)
        self.didChange.send(self)
    })
}
}

Which works if I display items In a list but the moment I use realm.deleteAll() the app crashes because it looks like Swift UI's list implementation is trying to diff the list, accessing the now invalidated realm db objects.

There are like 3 or 4 similar questions on stack overflow but they are all out of date in one way or another, or work but still have this issue when it comes to deletion.

Thanks!


Solution

  • Realm objects are live an autoupdating this is why they crash when you try to hold onto a deleted object. Instead of giving your publish subject the Realm.Object map it to a struct that has only the fields you need to use and use that array to drive SwiftUI.

    struct Event: Identifiable {
      var id: String
      var name: String
      var date: Date
    }
    
    final class DBData: ObservableObject {
    private var notificationTokens: [NotificationToken] = []
    var events = try! Realm().objects(ADMEvent.self)
    @Published var publishedEvents: [ADMEvent] = []
    init() {
        // Observe changes in the underlying model
        self.notificationTokens.append(posts.observe { _ in
            self.publishedEvents = events.map { Event(id: $0.id, name: $0.name, date: $0.date)}
        })
    }
    }