swiftuiswiftdata

Notifying a change in SwiftData @query


I have a SwiftData @Query which gives me a array of Event objects. Due to the nature of the object (e.g. dynamic distance calculations) I filter the events manually using function.

This works fine for any changes in the objects, and they are shown directly in the SwiftUI List. But If I add an object the List is not updated (as it is created from the filtered list, not directly from the @Quary).

Is there a way to subscribe to the @Quary to get a notification (or to pass the state on) so the data is refreshed? This is the relevant code, the data variable contains the data sorted by day and filtered using a normal function. FilterManager is an observable object, which notifies if the filter parameters change.

@State var data: [Date:[Event]] = [:]
@Query(sort: \Event.startTime) private var events: [Event]

List {
   ForEach(Array(data.keys).sorted(by: <), id: \.self) { day in
         Section(header: Text(day,format: Date.FormatStyle()
              .year(.defaultDigits)
              .month(.abbreviated)
              .day(.twoDigits)
              .weekday(.abbreviated)).font(.footnote)) {
                   ForEach(data[day]!) { item in
                          [...]
                   }
         }
 }.onAppear(){
    data = filterManager.sortedEvents(events: filterManager.filteredEvents(events: events))
 }.onReceive(filterManager.objectWillChange){
    data = filterManager.sortedEvents(events: filterManager.filteredEvents(events: events))
 }

Solution

  • Use a computed property (that depends on events), such as

    var data: [Date:[Event]] { 
       filterManager.sortedEvents(events: filterManager.filteredEvents(events: events)) 
    } 
    

    instead of

    @State var data: [Date:[Event]] = [:]