This error in TripListView indicates that the Query initializer you're calling expects a different type for the query result than the type being assigned to _trips.
Your code:
_trips = Query(
filter: filter,
sort: [sortDescriptor],
sectionBy: sectionBy
)
The key part of the error is:
[Trip] and SectionedResults<Trip, String> must be equivalent.
These are two different result types:
[Trip] — a regular array of trips.
SectionedResults<Trip, String> — sectioned query results grouped by a String key.
If you don't need sections, remove sectionBy from the initializer:
_trips = Query(
filter: filter,
sort: [sortDescriptor]
)
Your property can remain:
private var trips: [Trip]
If you're adapting Apple's sectioned TripListView, keep sectionBy, but declare the query result as sectioned results rather than [Trip].
For example, if the section key is a String:
private var trips: SectionedResults<Trip, String>
Then initialize the query:
_trips = Query(
filter: filter,
sort: [sortDescriptor],
sectionBy: sectionBy
)
if you change declaration of trips like this:
private var trips: SectionedResults<Trip, String>
The issue is that @Query(sectionBy: \Trip.destination) always produces SectionedResults<Trip, String>. When sectionBy == nil, you want to show all trips in one ungrouped list, but your current code still groups them by destination.
Because trips is declared as SectionedResults<Trip, String>, you cannot switch its underlying type to [Trip] conditionally in the initializer.
The clean solution is to use two separate query properties: one sectioned and one unsectioned, and choose which one to display.
Keep both query types. When sectionBy is nil, render allTrips; otherwise, render the grouped sectionedTrips.
import SwiftUI
import SwiftData
struct TripListView: View {
@Environment(\.modelContext) private var modelContext
// Unsectioned query: all trips
@Query private var allTrips: [Trip]
// Sectioned query: trips grouped by a String property
@Query private var sectionedTrips: SectionedResults<Trip, String>
@Binding var selection: Trip?
@Binding var tripCount: Int
@Binding var unreadTripIdentifiers: [PersistentIdentifier]
private let sectionBy: KeyPath<Trip, String>?
init(
selection: Binding<Trip?>,
segment: Binding<ContentView.Segment>,
tripCount: Binding<Int>,
unreadTripIdentifiers: Binding<[PersistentIdentifier]>,
searchText: String,
sectionBy: KeyPath<Trip, String>? = nil,
sortDescriptor: SortDescriptor<Trip> =
SortDescriptor(\Trip.startDate)
) {
_selection = selection
_tripCount = tripCount
_unreadTripIdentifiers = unreadTripIdentifiers
self.sectionBy = sectionBy
let filter = Self.buildPredicate(
segment: segment.wrappedValue,
searchText: searchText
)
// Always configure the unsectioned query.
_allTrips = Query(
filter: filter,
sort: [sortDescriptor]
)
// SectionedResults is required for this query.
// Use destination as a fallback when sectionBy is nil.
_sectionedTrips = Query(
filter: filter,
sort: [sortDescriptor],
sectionBy: sectionBy ?? \Trip.destination
)
}
var body: some View {
List(selection: $selection) {
if sectionBy == nil {
// Show all trips without section headers.
ForEach(allTrips) { trip in
TripListRow(
trip: trip,
isUnread: unreadTripIdentifiers.contains(
trip.persistentModelID
)
)
}
} else {
// Show trips grouped by the selected property.
ForEach(sectionedTrips.sections) { section in
Section(section.id) {
ForEach(section) { trip in
TripListRow(
trip: trip,
isUnread: unreadTripIdentifiers.contains(
trip.persistentModelID
)
)
}
}
}
}
}
}
}
Show all trips, without grouping
TripListView(
selection: $selection,
segment: $segment,
tripCount: $tripCount,
unreadTripIdentifiers: $unreadTripIdentifiers,
searchText: searchText,
sectionBy: nil
)
Group trips by destination
TripListView(
selection: $selection,
segment: $segment,
tripCount: $tripCount,
unreadTripIdentifiers: $unreadTripIdentifiers,
searchText: searchText,
sectionBy: \Trip.destination
)
This works fine!!!