@FetchRequest in SwiftUI — wat is het, Core Data ophalen en mechanisme

Auteur: IT Sectr Gepubliceerd: 2026-06-25 Leestijd: 8 min

@FetchRequest in SwiftUI — een property wrapper voor het automatisch ophalen van gegevens uit Core Data met reactieve update van de interface. De wrapper accepteert NSFetchRequest met filterpredicaten en sorteeropties, en het resultaat — een NSManagedObject-array — wordt automatisch bijgewerkt bij elke wijziging in de Core Data-context. Volgens Apple Developer Documentation (2025) vereist @FetchRequest een managedObjectContext in de SwiftUI-omgeving en ondersteunt het dynamische predicaten, wat zorgt voor een reactieve verbinding tussen Core Data en de gebruikersinterface.

Belangrijkste punten

  • @FetchRequest — property wrapper voor reactieve Core Data-ophaling in SwiftUI
  • Automatische update UI bij toevoegen, verwijderen of wijzigen van records in Core Data
  • Predicaten en sorteringen worden ingesteld in de initializer of via property wrapper-parameters
  • managedObjectContext moet beschikbaar zijn via @Environment in de View-hiërarchie
  • Dynamische predicaten maken het mogelijk filtervoorwaarden tijdens runtime te wijzigen

Wat is @FetchRequest in SwiftUI?

@FetchRequest — is een SwiftUI property wrapper die een FetchRequest uit Core Data maakt en beheert. Bij initialisatie accepteert de wrapper het entiteitstype, een NSSortDescriptor-array voor sortering en een optionele NSPredicate voor filtering. Het resultaat wordt opgeslagen als een array van objecten van het opgegeven NSManagedObject-type en wordt automatisch bijgewerkt bij wijzigingen in de persistentielaag.

Het belangrijkste kenmerk van @FetchRequest is reactiviteit. Wanneer gegevens in Core Data veranderen (save, insert, delete, update), voert SwiftUI automatisch een nieuwe ophaling uit en hertekent alle Views die deze fetch request gebruiken. De ontwikkelaar hoeft niet handmatig refresh aan te roepen, zich te abonneren op NSManagedObjectContextDidSaveNotification of gegevens opnieuw te laden. SwiftUI beheert de volledige synchronisatiecyclus.

Voor de werking van @FetchRequest is NSManagedObjectContext vereist, beschikbaar in de SwiftUI-omgeving via @Environment(\.managedObjectContext). De context wordt meestal doorgegeven vanuit de root van de applicatie, waar NSPersistentContainer wordt aangemaakt. Het standaardpatroon — gebruik van ViewModel of App-structuur voor het configureren van de Core Data-stack en het doorgeven van de context via de .environment()-modifier.

Sorteren en predicaten van FetchRequest

@FetchRequest accepteert verschillende parameters voor het configureren van de ophaling. SortDescriptors — een NSSortDescriptor-array die de volgorde van records bepaalt. Predicate — NSPredicate voor filtering, bijvoorbeeld het ophalen van alleen taken met de status „voltooid”. Animation — animatie voor het bijwerken van de lijst bij gegevenswijzigingen.

Core Data-predicaten gebruiken een SQL-achtige expressie-indeling: NSPredicate(format: „status == %@”, „completed”). Meerdere voorwaarden kunnen worden gecombineerd via AND, OR en NOT. SortDescriptors bepalen de volgorde: NSSortDescriptor(keyPath: \Task.dueDate, ascending: true). Voor sortering op meerdere velden wordt een array van descriptoren doorgegeven — de eerste wordt toegepast als hoofd-, de rest als secundaire.

swift
struct TaskListView: View {
    @Environment(\.managedObjectContext) var viewContext

    @FetchRequest(
        sortDescriptors: [
            NSSortDescriptor(keyPath: \.Task.dueDate, ascending: true),
            NSSortDescriptor(keyPath: \.Task.priority, ascending: false)
        ],
        predicate: NSPredicate(format: "isCompleted == NO"),
        animation: .default
    )
    var tasks: FetchedResults<Task>

    var body: some View {
        List(tasks) { task in
            Text(task.title ?? "")
        }
    }
}

In het voorbeeld selecteert @FetchRequest alle onvoltooide taken (isCompleted == NO), eerst gesorteerd op datum (oplopend), daarna op prioriteit (aflopend). FetchedResults<Task> — een automatisch bijgewerkte collectie die zich gedraagt als een array voor ForEach en List. De .default-animatie zorgt voor een vloeiende weergave/verdwijning van records bij wijzigingen.

@FetchRequest met List en dynamische gegevens

@FetchRequest combineert ideaal met List en ForEach voor het weergeven van dynamische Core Data-lijsten. Het ophaalresultaat (FetchedResults) voldoet aan het RandomAccessCollection-protocol, dus het kan direct worden gebruikt in List en ForEach. Bij toevoegen, verwijderen of wijzigen van records wordt de lijst automatisch met animatie hertekend.

Voor het verwijderen van records wordt de delete-methode van de context gebruikt. Voor toevoegen — het maken van een nieuw NSManagedObject en het aanroepen van save. Alle wijzigingen worden uitgevoerd via viewContext, die samen met @FetchRequest de gegevensconsistentie waarborgt. Voor bewerking wordt @ObservedObject of @Bindable gebruikt voor een specifiek Core Data-object.

swift
struct TaskListWithActions: View {
    @Environment(\.managedObjectContext) var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \.Task.createdAt,
                                               ascending: false)]
    )
    var tasks: FetchedResults<Task>

    var body: some View {
        List {
            ForEach(tasks) { task in
                HStack {
                    Text(task.title ?? "")
                    Spacer()
                    Image(systemName: task.isCompleted
                               ? "checkmark.circle.fill"
                               : "circle")
                }
                .onTapGesture { toggleTask(task) }
            }
            .onDelete(perform: deleteTasks)
        }
        .toolbar {
            Button(systemImage: "toevoegen") { addTask() }
        }
    }

    private func addTask() {
        let newTask = Task(context: viewContext)
        newTask.title = "New task \(tasks.count + 1)"
        newTask.createdAt = Date()
        try? viewContext.save()
    }

    private func toggleTask(_ task: Task) {
        task.isCompleted.toggle()
        try? viewContext.save()
    }

    private func deleteTasks(at offsets: IndexSet) {
        for index in offsets {
            viewContext.delete(tasks[index])
        }
        try? viewContext.save()
    }
}

Dit voorbeeld demonstreert volledige CRUD met @FetchRequest. Toevoegen: Task maken via context en save(). Verwijderen: delete() op context en save(). Bijwerken: toggle van eigenschap en save(). Na elke save() voert @FetchRequest automatisch een nieuwe gegevensophaling uit en werkt de List bij met animatie. De modifiers onDelete en onTapGesture bieden standaard iOS-interacties.

Dynamische predicaten tijdens runtime

@FetchRequest ondersteunt dynamische predicaten via de parameter predicate die tijdens runtime kan worden gewijzigd. Hiervoor moet u @FetchRequest maken met een variabele-predicaat en deze doorgeven via Binding. Wanneer de gebruiker het filter wijzigt — bijvoorbeeld een taakcategorie selecteert — wordt het predicaat bijgewerkt en wordt de ophaling automatisch opnieuw gestart.

Dynamische predicaten worden geïmplementeerd via een @State- of @Published-eigenschap, die als Binding wordt doorgegeven aan de initializer van @FetchRequest. SwiftUI volgt de wijziging van deze Binding en maakt opnieuw een NSFetchRequest met het nieuwe predicaat, waardoor de lijst automatisch wordt bijgewerkt.

Codevoorbeelden @FetchRequest

Laten we een volledig voorbeeld bekijken van een dagboekapplicatie met @FetchRequest voor het ophalen van records. Het zoekformulier gebruikt een dynamisch predicaat: bij het invoeren van tekst werkt FetchRequest automatisch de resultaten bij, waarbij records worden gefilterd op titel en inhoud. Sortering — op aanmaakdatum, van nieuw naar oud.

swift
struct JournalEntryView: View {
    @Environment(\.managedObjectContext) var viewContext
    @State private var searchText = ""

    private var searchPredicate: NSPredicate? {
        guard !searchText.isEmpty else { return nil }
        return NSPredicate(format: "title CONTAINS[c] %@", searchText)
    }

    @FetchRequest var entries: FetchedResults<JournalEntry>

    init(searchText: String) {
        let sort = [NSSortDescriptor(keyPath: \.JournalEntry.date,
                                           ascending: false)]
        let pred: NSPredicate? = searchText.isEmpty
            ? nil
            : NSPredicate(format: "title CONTAINS[c] %@ OR content CONTAINS[c] %@",
                          searchText, searchText)
        self._entries = FetchRequest(
            sortDescriptors: sort,
            predicate: pred,
            animation: .default
        )
    }

    var body: some View {
        List(entries) { entry in
            VStack(alignment: .leading) {
                Text(entry.title ?? "").font(.headline)
                Text(entry.content ?? "").font(.subheadline)
                    .lineLimit(2)
            }
        }
        .searchable(text: $searchText)
    }
}

Dagboek met zoekfunctie: bij het invoeren van tekst in het searchable-veld wordt NSPredicate met CONTAINS[c] (hoofdletterongevoelig zoeken) gemaakt op de velden title en content. Init accepteert searchText en maakt FetchRequest met het bijbehorende predicaat. De Searchable-modifier werkt automatisch searchText bij, en @FetchRequest reageert op de verandering van het predicaat en voert een nieuwe gegevensophaling uit.

Voor complexere scenarioën met meerdere filters combineert u NSCompoundPredicate met AND/OR-logica. @FetchRequest ondersteunt predicaten van elke complexiteit, inclusief geneste subquery’s (SUBQUERY) voor filtering op relaties. Onthoud echter: complexe predicaten beïnvloeden de prestaties — voor grote datasets (meer dan 10.000 records) gebruikt u Core Data-indexering en beperkt u de ophaling via fetchLimit.

Veelgestelde vragen

Hoe geef ik managedObjectContext door aan @FetchRequest?

Voeg @Environment(\.managedObjectContext) var viewContext toe aan de root-View en geef het door via de modifier .environment(\.managedObjectContext, context). Alle onderliggende Views die @FetchRequest gebruiken, krijgen automatisch de context uit de omgeving.

Kan @FetchRequest worden bijgewerkt zonder de View opnieuw te laden?

Ja, wijzig de Core Data-context: voeg een object toe, verwijder het of werk het bij en roep save() aan. @FetchRequest voert automatisch een nieuwe ophaling uit en werkt de UI bij. Voor een geforceerde update zonder save() gebruikt u viewContext.refreshAllObjects().

Wat is het verschil tussen @FetchRequest en @SectionedFetchRequest?

@FetchRequest retourneert een platte array van objecten. @SectionedFetchRequest groepeert resultaten op het opgegeven key-path in secties, vergelijkbaar met UITableView met sectionNameKeyPath. Gebruik @SectionedFetchRequest voor gegroepeerde lijsten met sectiekopteksten.

Hoe gebruik ik @FetchRequest met Relationship?

Gebruik voor filtering op relaties de puntnotatie: NSPredicate(format: „category.name == %@”, „Work”). @FetchRequest voert automatisch JOIN uit in SQLite. Voor toegang tot de relatie via het geselecteerde object gebruikt u de gewone NSManagedObject-eigenschappen.

Ondersteunt @FetchRequest paginering?

@FetchRequest ondersteunt geen directe paginering, omdat het bedoeld is voor het weergeven van alle records met reactieve updates. Gebruik voor paginering NSFetchRequest met fetchLimit/fetchOffset en laad de gegevens handmatig bij het scrollen door de lijst.

Samenvatting

  • @FetchRequest — property wrapper voor automatische reactieve Core Data-ophaling in SwiftUI
  • Sortering ingesteld met NSSortDescriptor-array, filtering — met NSPredicate
  • Automatische update UI bij elke gegevenswijziging in de Core Data-context
  • managedObjectContext doorgegeven via @Environment in de View-hiërarchie
  • Dynamische predicaten geïmplementeerd via custom init met predicaatparameter
  • CRUD-bewerkingen uitgevoerd via viewContext met automatische lijstsynchronisatie
  • Gebruik @FetchRequest voor Core Data-weergave, @SectionedFetchRequest — voor gegroepeerde lijsten

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook