TechnologiesSwiftUI

SectionedFetchRequest struct

iOSmacOStvOSwatchOSvisionOSiOS 15.0+✓ renders

A property wrapper type that retrieves entities, grouped into sections,

How it works

Use a SectionedFetchRequest property wrapper to retrieve Core Data managed objects from a view and have SwiftUI deliver them already grouped into sections. Unlike a flat FetchRequest, which hands you a single ordered collection, SectionedFetchRequest splits its results by a key path you choose and exposes the groups as a SectionedFetchResults value, so each section arrives with its own identifier and contents. Reach for it when your data is naturally partitioned — items by category, events by date, contacts by initial — and you want the store, rather than your view code, to do the grouping. Because the request lives in the view, the sections stay in sync with the managed object context and refresh automatically as the underlying data changes.

  1. Declare the request with @SectionedFetchRequest

    Apply the property wrapper to a property in your view and supply a sectionIdentifier key path together with sort descriptors. The sectionIdentifier names the field that defines each group's boundary, and the sort descriptors must order results so that rows sharing a section value are adjacent. In the example the page's category field plays the grouping role that this key path would target — "Fruit" and "Vegetable" become the section boundaries.

  2. Read the grouped results as SectionedFetchResults

    The wrapped value is a SectionedFetchResults collection whose elements are sections rather than individual objects. You iterate it to walk the groups, and each element carries an id matching its sectionIdentifier plus the managed objects that fall under it. This two-level shape mirrors the sections array in the example, where each entry pairs a title with its items.

  3. Render each section's id and elements

    Drive a List by iterating the results: the outer loop yields one section per sectionIdentifier value, and the inner loop yields that section's objects. Use the section's identifier for the header and its contents for the rows — the structure the code shows with ForEach(sections, id: \.0) wrapping a Section(header: Text(title)) and an inner ForEach(items) over each item.

  4. Customize the underlying query and grouping at runtime

    SectionedFetchResults exposes a settable sectionIdentifier, nsSortDescriptors, and nsPredicate, letting you re-section, re-sort, or filter without redeclaring the request. Assigning a new sectionIdentifier reshapes the same data into different groups — the equivalent of swapping which field of Item (its category versus its name) decides the Section boundaries.

Try it — Change the grouping key from the category field to name (for example, the first letter of item.name) so the request re-sections the same items alphabetically, and watch the Section(header:) titles change from "Fruit"/"Vegetable" to letter buckets.

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.

SectionedFetchRequest.swift
struct SectionedFetchRequestDemo: View {
    struct Item: Identifiable {
        let id = UUID()
        let name: String
        let category: String
    }

    let sections: [(String, [Item])] = [
        ("Fruit", [Item(name: "Apple", category: "Fruit"), Item(name: "Banana", category: "Fruit")]),
        ("Vegetable", [Item(name: "Carrot", category: "Vegetable")])
    ]

    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 →