Core Data — kernconcepten, NSManagedObject en architectuur

Auteur: IT Sectr Gepubliceerd: 2026-03-11 Leestijd: 11 min

Core Data — het Apple-framework voor het beheren van een objectgraaf in iOS- en macOS-apps. Het zorgt voor gegevenspersistentie, het bijhouden van wijzigingen, het ongedaan maken van bewerkingen en integratie met de UI via NSFetchedResultsController. Volgens de Apple Developer-documentatie (2025) is Core Data geen database — het is een objectmodelleringslaag die standaard SQLite gebruikt als permanente opslag voor het laden en opslaan van objecten.

Belangrijkste punten

  • Core Data — ORM-framework voor iOS/macOS dat de objectgraaf en het opslaan ervan in permanente opslag beheert.
  • NSManagedObjectModel — het gegevensschema dat entiteiten, attributen en relaties tussen objecten in het Core Data-model beschrijft.
  • NSManagedObjectContext — werkruimte voor het maken, lezen, bijwerken en verwijderen van objecten met wijzigingsregistratie.
  • NSPersistentContainer — enkel ingangspunt dat het model, de context en de opslag van Core Data in iOS 10+ inkapselt.
  • NSFetchedResultsController — klasse voor integratie van Core Data met UITableView/UICollectionView met automatische updates bij wijzigingen.

Wat is Core Data?

Core Data — is een framework voor objectgraafbeheer en persistentie, onderdeel van de Cocoa Touch SDK van Apple. Het biedt een objectgeoriënteerde interface voor het werken met gegevens: de ontwikkelaar werkt met entiteiten (Entity), attributen en relaties (Relationship), en Core Data zet deze objecten onder de motorkap om in records van een relationele database.

Core Data werd geïntroduceerd in Mac OS X 10.4 Tiger (2005) voor macOS en overgezet naar iOS 3.0 (2009). In meer dan 20 jaar is het framework geëvolueerd van een eenvoudige abstractielaag boven SQLite tot een volledige stack met ondersteuning voor cloudsynchronisatie via NSPersistentCloudKitContainer, multithreading via automatisch contextbeheer en asynchroon laden via Swift Concurrency.

Volgens een enquête onder iOS-ontwikkelaars van Slack Community (2025) wordt Core Data gebruikt in 68% van de commerciële iOS-apps voor lokale gegevensopslag. Ondanks kritiek op complexiteit en gelaagdheid blijft het framework de standaard voor Apple-apps dankzij nauwe integratie met het systeem, nul kosten (ingebouwd in SDK) en ondersteuning voor iCloud-synchronisatie.

Core Data is geen database

Een veelvoorkomend misverstand — om Core Data als een database te beschouwen. Het framework voert geen SQL-query's rechtstreeks uit en is geen DBMS. Core Data is een objectbeheerlaag (object graph management) die SQLite, Binary of In-Memory kan gebruiken voor persistentie. Analogie: Core Data is als ORM zoals Hibernate of Entity Framework, maar voor het Apple-ecosysteem, en SQLite eronder — zoals MySQL onder Hibernate.

Core Data-architectuur: stacks en componenten

De Core Data-stack bestaat uit vier onderling verbonden componenten: NSManagedObjectModel (gegevensschema), NSPersistentStoreCoordinator (opslagcoördinator), NSManagedObjectContext (werkcontext) en NSPersistentContainer (uniforme container die alle drie combineert vanaf iOS 10). NSPersistentContainer automatiseert het maken en configureren van de stack.

Elke component vervult een strikt gedefinieerde functie. NSManagedObjectModel laadt het .xcdatamodeld-bestand met de beschrijving van entiteiten. NSPersistentStoreCoordinator koppelt het model aan het fysieke opslagbestand (SQLite). NSManagedObjectContext biedt een tijdelijke ruimte voor het werken met objecten. De container combineert alles in een enkele initialisatieaanroep.

Typen Core Data-opslag

SQLite (NSSQLiteStoreType) — de standaardopslag die in de meeste apps wordt gebruikt. Gegevens worden opgeslagen in één .sqlite-bestand met ondersteuning voor ACID-transacties. Binary (NSBinaryStoreType) — opslag in binair formaat voor kleine datasets (tot enkele honderden objecten). In-Memory (NSInMemoryStoreType) — tijdelijke opslag in RAM zonder opslag op schijf, gebruikt voor tests en cache.

OpslagtypeFormaatPrestatiesWanneer gebruiken
SQLite.sqliteHoogStandaardkeuze voor productie
Binary.binaryGemiddeldKleine datasets
In-MemoryRAMMaximaalTests, cache, tijdelijke gegevens
CloudKitiCloudAfhankelijk van netwerkSynchronisatie tussen apparaten

De opslagkeuze wordt met een enkele regel ingesteld bij de initialisatie van NSPersistentStoreDescription. De ontwikkelaar kan de opslag overschakelen van SQLite naar In-Memory voor unittesten of naar CloudKit voor iCloud-synchronisatie zonder de code voor het werken met objecten te wijzigen — Core Data abstraheert het verschil tussen opslagtypes via een uniforme context-API.

NSManagedObject en NSManagedObjectContext

NSManagedObject — de basisklasse voor alle Core Data-objecten die één entiteitsrecord vertegenwoordigt. Elk managed object heeft een unieke NSManagedObjectID (permanente identifier), is gekoppeld aan een context en houdt zijn wijzigingen bij via KVO (Key-Value Observing). De ontwikkelaar maakt subklassen van NSManagedObject om getypeerde eigenschappen van de entiteit te definiëren.

NSManagedObjectContext — het centrale onderdeel van Core Data dat een werkruimte biedt voor alle objectbewerkingen. De context houdt toevoegingen, verwijderingen en wijzigingen van objecten bij (change tracking), ondersteunt het ongedaan maken van bewerkingen via undoManager en voegt automatisch wijzigingen uit andere contexten samen bij ontvangst van opslagmeldingen.

Thread-veiligheid van contexten

Regel voor privé-wachtrijen: NSManagedObjectContext wordt gemaakt met het type .privateQueueConcurrencyType of .mainQueueConcurrencyType. De hoofdcontext is gekoppeld aan de hoofd-UI-thread, privécontexten worden uitgevoerd op achtergrondwachtrijen. Elke context mag alleen in zijn eigen wachtrij worden gebruikt — toegang tot een managed object vanuit een andere thread veroorzaakt een crash. parentContext maakt het mogelijk een hiërarchie van contexten te organiseren voor asynchroon schrijven.

swift
struct CoreDataStack {
    let container: NSPersistentContainer

    init(name: String) {
        container = NSPersistentContainer(name: name)
        container.loadPersistentStores { _, error in
            if let error = error {
                fatalError("Failed to load store: \(error)")
            }
        }
        container.viewContext.automaticallyMergesChangesFromParent = true
    }

    func backgroundContext() -> NSManagedObjectContext {
        let context = container.newBackgroundContext()
        context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        return context
    }
}

NSPersistentContainer maakt automatisch viewContext (main queue) aan en biedt newBackgroundContext() voor achtergrondbewerkingen. De eigenschap automaticallyMergesChangesFromParent = true zorgt ervoor dat viewContext automatisch wijzigingen uit achtergrondcontexten overneemt wanneer deze worden opgeslagen, waarbij de UI wordt bijgewerkt zonder handmatig opnieuw opvragen van gegevens.

Persistent Store en de relatie met SQLite

NSPersistentStoreCoordinator beheert de fysieke gegevensopslag: opent het bestand, maakt SQLite-tabellen op basis van het model, voert migraties uit bij schema-wijzigingen. Bij initialisatie van NSPersistentStoreDescription met het type NSSQLiteStoreType maakt Core Data een SQLite-bestand met een schema dat overeenkomt met het .xcdatamodeld-model.

Core Data gebruikt geen standaard SQL-query's via SELECT/INSERT/UPDATE. In plaats daarvan genereert het interne SQL-opdrachten op basis van het model en query's via NSFetchRequest. De ontwikkelaar kan SQL-logging inschakelen via de opstartparameter -com.apple.CoreData.SQLDebug 1 voor het debuggen van query-prestaties.

Core Data-migraties

Lichte migratie (Lightweight Migration) — het automatische proces van het bijwerken van het SQLite-schema bij het toevoegen van nieuwe attributen, het wijzigen van optional/required of het hernoemen met behulp van renamingID. Zware migratie is nodig bij ingrijpende schema-wijzigingen zoals het samenvoegen of splitsen van entiteiten en wordt uitgevoerd via een aangepaste NSMigrationManager.

swift
let description = NSPersistentStoreDescription()
description.url = FileManager.default
    .urls(for: .documentDirectory, in: .userDomainMask)
    .first?
    .appendingPathComponent("Model.sqlite")
description.setOption(true as NSNumber,
    forKey: NSMigratePersistentStoresAutomaticallyOption)
description.setOption(true as NSNumber,
    forKey: NSInferMappingModelAutomaticallyOption)

let container = NSPersistentContainer(name: "AppModel")
container.persistentStoreDescriptions = [description]
container.loadPersistentStores { _, error in
    if let error = error { print("Migration error: \(error)") }
}

Configuratie van automatische migratie via NSMigratePersistentStoresAutomaticallyOption en NSInferMappingModelAutomaticallyOption stelt Core Data in staat het SQLite-bestand zelfstandig bij te werken bij het toevoegen van attributen of entiteiten in een nieuwe versie van het model. Als migratie niet mogelijk is, gooit de store coordinator een fout met een beschrijving van de reden — de ontwikkelaar moet een aangepaste migratie implementeren via NSMigrationManager.

Core Data in de praktijk: code en voorbeelden

NSFetchRequest — het belangrijkste hulpmiddel voor het ophalen van objecten uit Core Data. De query bevat de entiteitsnaam, een predicaat (filter), sorteringen, limiet en offset. Het resultaat wordt geretourneerd als een array van NSManagedObject of getypeerde subklassen. NSPredicate ondersteunt complexe voorwaarden met AND, OR, IN, LIKE en subquery's.

NSBatchDeleteRequest — een efficiënte manier om objecten in bulk te verwijderen zonder elk object in het geheugen te laden. De query wordt uitgevoerd op SQLite-niveau, waarbij de managed object context wordt omzeild, en werkt de context pas bij na voltooiing. Vergelijkbare batch-query's bestaan voor bijwerken (NSBatchUpdateRequest) en invoegen (NSBatchInsertRequest).

Voorbeeld van CRUD-bewerkingen

CRUD (Create, Read, Update, Delete) in Core Data wordt uitgevoerd via contextmethoden: insert, fetch, save en delete. Alle wijzigingen zijn tijdelijk tot de aanroep van context.save() — de methode slaat wijzigingen op in de permanente SQLite-opslag. Bij een opslagfout blijft de context in gewijzigde staat voor een nieuwe poging.

swift
let context = container.viewContext

// Aanmaken
let user = User(context: context)
user.id = 42
user.name = "Alice"

// Lezen
let request = User.fetchRequest()
request.predicate = NSPredicate(format: "name CONTAINS %@", "Ali")
request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
let results = try context.fetch(request)

// Bijwerken
results.first?.name = "Alice Updated"

// Verwijderen
if let first = results.first { context.delete(first) }

// Opslaan
try context.save()

Opslaan van de context (context.save()) — een kritieke bewerking. Als opslaan niet wordt aangeroepen, blijven alle wijzigingen alleen in het geheugen. De context houdt de status hasChanges bij, die vóór opslaan kan worden gecontroleerd. Gebruik voor achtergrondbewerkingen newBackgroundContext met eigen opslag, en voor UI — viewContext met automatische opslag op timer of wanneer de app naar de achtergrond gaat.

Beste praktijken voor Core Data

Eerste praktijk — gebruik NSPersistentCloudKitContainer voor het synchroniseren van gegevens tussen de apparaten van de gebruiker via iCloud. Cloudsynchronisatie wordt ingeschakeld door een CloudKit-optie toe te voegen aan de opslagbeschrijving. Core Data beheert automatisch conflicten tijdens synchronisatie en voegt wijzigingen van andere apparaten samen.

Tweede praktijk — vermijd fetchRequest zonder predicaat op grote tabellen. Elke onvoorwaardelijke query laadt alle objecten van de entiteit in het geheugen, wat leidt tot hoog RAM-gebruik en vertraging van de UI. Gebruik altijd predicaten en limieten. Gebruik voor paginering fetchLimit en fetchOffset in NSFetchRequest.

Derde praktijk — configureer mergePolicy voor het oplossen van conflicten bij multi-thread-toegang. NSMergeByPropertyObjectTrumpMergePolicy werkt conflicterende eigenschappen bij vanuit de laatst opgeslagen context. NSRollbackMergePolicy annuleert wijzigingen van de huidige context bij een conflict. De keuze van het beleid hangt af van de bedrijfslogica van de app.

Vierde praktijk — gebruik NSFetchedResultsController voor integratie met tabellen en verzamelingen. Het abonneert zich automatisch op NSManagedObjectContextDidSave-meldingen, laadt alleen de benodigde objecten (faulting) en stelt de gedelegeerde op de hoogte van invoegingen, verwijderingen en verplaatsingen met de juiste indexpaden voor UITableView-animatie.

Prestaties: prefetching en faulting

Faulting — het mechanisme voor lui laden van Core Data-objecten. Een door een fetch-query geretourneerd managed object bevindt zich in de fault-status — de attributen zijn niet volledig geladen, alleen de identifier. Volledig laden (fire fault) vindt plaats bij de eerste toegang tot een attribuut. Relationship prefetching (setRelationshipKeyPathsForPrefetching) laadt gerelateerde objecten vooraf, waardoor N+1-query's worden voorkomen.

swift
extension UserRepository {
    func fetchUsersWithPosts() throws -> [User] {
        let request = User.fetchRequest()
        request.predicate = NSPredicate(format: "isActive == YES")
        request.relationshipKeyPathsForPrefetching = ["posts"]
        request.returnsObjectsAsFaults = false
        request.fetchBatchSize = 20

        let context = container.viewContext
        return try context.fetch(request)
    }
}

fetchBatchSize = 20 dwingt Core Data om gegevens in porties van 20 objecten te laden (voor weergave op het scherm), zonder de hele tabel in één keer te laden. De vlag returnsObjectsAsFaults = false garandeert dat attributen van alle gebruikers onmiddellijk worden geladen, wat handig is bij directe weergave. Prefetching van de relatie "posts" voorkomt afzonderlijke query's voor elke gebruiker bij toegang tot berichten.

Veelgestelde vragen

Is Core Data een database?

Nee, Core Data is een framework voor objectgraafbeheer. Het biedt een API voor het werken met objecten, het bijhouden van wijzigingen en het opslaan ervan. De database onder Core Data (standaard SQLite) moet niet worden verward met het framework zelf. Core Data is een ORM, geen DBMS.

Kan Core Data worden gebruikt zonder SQLite?

Ja, Core Data ondersteunt drie typen opslag: SQLite, Binary en In-Memory. De opslagkeuze wordt ingesteld via NSPersistentStoreDescription. In-Memory-opslag slaat geen gegevens op schijf op en is geschikt voor unittesten. Binary-opslag is een verouderd formaat voor compacte objectverzamelingen.

Hoe migreer ik Core Data naar een nieuwe modelversie?

Schakel voor lichte migratie NSMigratePersistentStoresAutomaticallyOption en NSInferMappingModelAutomaticallyOption in. Maak voor complexe wijzigingen een Mapping Model (.xcmappingmodel) via Xcode. CloudKit-opslag (NSPersistentCloudKitContainer) ondersteunt migraties automatisch bij het synchroniseren van het schema met de iCloud-server.

Wat is het verschil tussen Core Data en SwiftData?

SwiftData — is een nieuw Apple-framework (iOS 17+), gebouwd bovenop Core Data met Swift Macros en Swift Concurrency. SwiftData is eenvoudiger in syntaxis: entiteiten worden beschreven met de @Model-macro, context — met @Environment(\.modelContext). Onder de motorkap gebruikt SwiftData dezelfde Core Data-stack en SQLite.

Hoe debug ik trage Core Data-query's?

Schakel de opstartparameter -com.apple.CoreData.SQLDebug 1 in — Core Data geeft alle SQL-query's en hun duur weer in de Xcode-console. Gebruik voor profilering Instruments met het Core Data-sjabloon, dat het aantal fault-query's, objectlading en contextopslagtijd toont.

Samenvatting

  • Core Data — framework voor objectgraafbeheer en gegevenspersistentie voor iOS en macOS, dat SQLite gebruikt als standaardopslag.
  • Core Data-stack omvat NSManagedObjectModel, NSPersistentStoreCoordinator, NSManagedObjectContext en NSPersistentContainer voor uniforme configuratie.
  • NSManagedObjectContext — werkruimte met wijzigingsregistratie, ondersteuning voor ongedaan maken en automatisch samenvoegen uit achtergrondcontexten.
  • NSFetchRequest met NSPredicate en prefetching — het belangrijkste ophaalhulpmiddel met optimalisatie via batch size en faulting.
  • Lightweight Migration werkt automatisch het SQLite-schema bij bij het toevoegen van Core Data-attributen en entiteiten in een nieuwe modelversie.
  • NSPersistentCloudKitContainer voegt iCloud-synchronisatie toe tussen de apparaten van de gebruiker met automatische conflictoplossing.
  • Aanbeveling — gebruik Core Data voor iOS-apps met hiërarchische objectmodellen, en overweeg voor eenvoudige lokale opslag GRDB of SwiftData.

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