How it works
SectionedFetchResults is a collection of Core Data managed objects that SwiftUI retrieves and then groups into sections for you, so that fetched data arrives already organized by a shared key. You don't create it directly; the @SectionedFetchRequest property wrapper produces and maintains an instance, keeping it in sync as the underlying store changes. Reach for it when a list needs section headers driven by your data — alphabetized contacts, transactions by month, items by category — rather than flattening everything into a single stream of rows.
Iterate the results as a sequence of sections
SectionedFetchResults conforms to RandomAccessCollection, but its Element is a Section rather than a single managed object. Each element carries an
id(the section key value) and acts as a collection of the objects that share that key, which is what lets you nest one loop inside another — an outer pass over the sections and an inner pass over each section's items, mirrored here by the outerForEach(sections, id: \.0)and the innerForEach(items).Read the grouping key from each section's id
Every section exposes the value that all of its objects share through its
idproperty, typed by the request's SectionIdentifier. That value is the natural source for a header, the way the example pulls the groupingtitleout of each tuple to buildSection(header: Text(title)).Bind it inside a List with Section
Because SectionedFetchResults is a collection, it slots directly into a SwiftUI
List, and its per-section structure lines up one-to-one with theSectionview. You walk the results to emit aSectionfor each group and render that group's objects inside it, exactly the nesting the example sketches withList,Section, andText(item.name).Stay current as the store changes
An instance owned by @SectionedFetchRequest is live: when objects are inserted, deleted, or change the value of their section key, SwiftUI re-fetches, re-groups, and invalidates the view so the section list reflects the new state — the membership and even the number of sections can shift between renders without any manual reload.
sections whose key reuses an existing group — e.g. append ("Fruit", [Item(name: "Cherry")]) — and watch that the grouping is keyed by value, so where it lands depends on how the section identifier collapses matching keys.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct SectionedFetchResultsDemo: View {
struct Item: Identifiable { let id = UUID(); let name: String }
let sections: [(String, [Item])] = [
("Fruit", [Item(name: "Apple"), Item(name: "Banana")]),
("Vegetable", [Item(name: "Carrot"), Item(name: "Pepper")])
]
var body: some View {
List {
ForEach(sections, id: \.0) { title, items in
Section(header: Text(title)) {
ForEach(items) { item in
Text(item.name)
}
}
}
}
.padding()
}
}