SwiftData Sectioning iOS 27

I try Apple: Adopting SwiftData for a Core Data App . But I have error " 'init(filter:sort:transaction:sectionBy:)' requires the types '[Trip]' and 'SectionedResults<Array<Trip>.Element, String>' (aka 'SectionedResults<Trip, String>') be equivalent"

at code line Query(filter: filter, sort: [sortDescriptor], sectionBy: sectionBy)

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.

Fix 1: If you want a regular list of trips

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]

Fix 2: If you want trips grouped into sections

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.

Updated TripListView

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
                                )
                            )
                        }
                    }
                }
            }
        }
    }
}

How to call it

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!!!