TechnologiesSwiftUI

SectionedFetchResults struct

iOSmacOStvOSwatchOSvisionOSiOS 15.0+✓ renders

A collection of results retrieved from a Core Data persistent store,

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.

  1. 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 outer ForEach(sections, id: \.0) and the inner ForEach(items).

  2. Read the grouping key from each section's id

    Every section exposes the value that all of its objects share through its id property, typed by the request's SectionIdentifier. That value is the natural source for a header, the way the example pulls the grouping title out of each tuple to build Section(header: Text(title)).

  3. 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 the Section view. You walk the results to emit a Section for each group and render that group's objects inside it, exactly the nesting the example sketches with List, Section, and Text(item.name).

  4. 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.

Try it — Add a third entry to 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.

SectionedFetchResults.swift
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()
    }
}
Live preview
swift → lexer → parser → sema → uiir → canvas Open in Studio ↗
What's new in SwiftUI 27 →