Core Data ist ein Apple-Framework zur Datenverwaltung, das objektrelationale Abbildung für iOS, macOS, tvOS und watchOS bereitstellt. Es automatisiert das Speichern, Abrufen und Filtern von Objekten in der Anwendung und arbeitet auf SQLite-, XML- oder Binärspeicherbasis. Laut Apple Core Data Documentation verwendet das Framework die Konzepte Managed Object Context und NSPersistentContainer zur Verwaltung des Persistenz-Stacks.
Wichtige Punkte
Core Data ist ein Framework zur Verwaltung von Objektgraphen und Persistenz, das Teil von Cocoa Touch ist. Entgegen einem weit verbreiteten Missverständnis ist Core Data keine Datenbank, sondern eine Objektverwaltungsschicht, die SQLite als einen ihrer Speicher verwenden kann. Die Hauptaufgabe von Core Data besteht darin, Objektänderungen zu verfolgen, deren Lebenszyklus zu verwalten und den Zustand mit der Festplatte zu synchronisieren.
Das Framework stellt einen Objektgraphen bereit, bei dem jedes Managed Object vom Kontext auf Änderungen überwacht wird. Beim Speichern werden alle geänderten, hinzugefügten und gelöschten Objekte in einer einzigen Transaktion im persistenten Speicher festgeschrieben. Dadurch entfällt die Notwendigkeit für den Entwickler, SQL-Abfragen zu schreiben und Transaktionen manuell zu verwalten.
Laut Statistiken der Swift Developer Survey (2025) wird Core Data in 52% der iOS-Anwendungen verwendet, die mit lokalen Daten arbeiten. Trotz des Aufkommens moderner Alternativen (SwiftData, Realm) bleibt Core Data aufgrund seiner Reife und tiefen Systemintegration das primäre Framework in bestehenden Apple-Projekten.
Verwenden Sie Core Data für Projekte mit einem Datenmodell mittlerer Komplexität, bei denen Objektbeziehungen, Rückgängigmachen von Änderungen und automatisches Caching durch den Faulting-Mechanismus benötigt werden.
Die Architektur von Core Data ist um das Konzept des Managed Object Context aufgebaut — eines Arbeitsbereichs, der alle Objektänderungen verfolgt. Der Kontext unterstützt Rückgängig/Wiederholen über den integrierten NSUndoManager, was die Implementierung von Entwürfen und Aktionsabbrüchen ermöglicht, ohne manuell Zustands-Snapshots speichern zu müssen. Beim Aufruf von save() schreibt der Kontext alle Änderungen in einer einzigen Transaktion in den persistenten Speicher, wodurch Atomizität und Datenkonsistenz gewährleistet werden.
Das Core Data-Datenmodell wird in der .xcdatamodeld-Datei definiert — dem visuellen Editor von Xcode, in dem alle Entities, ihre Attribute und Beziehungen beschrieben werden. Bei der Kompilierung wird das Modell in .momd serialisiert und über NSManagedObjectModel geladen.
Entity ist eine Datenbeschreibung, ähnlich einer Tabelle in SQL. Jede Entity enthält eine Reihe von Attributes — benannte Felder mit einem Datentyp (String, Integer, Date, Boolean, Data). Im Gegensatz zu Room erfordert Core Data eine explizite Typauswahl für jedes Attribut über den Modelleditor.
Relationship ist eine Verbindung zwischen Entities, ähnlich einem Fremdschlüssel in SQL. Core Data unterstützt alle Beziehungstypen: eins-zu-eins, eins-zu-viele und viele-zu-viele. Für jede Beziehung wird eine Delete Rule (Cascade, Nullify, Deny) konfiguriert — das Verhalten beim Löschen des zugehörigen Objekts.
| Delete Rule | Verhalten beim Löschen | Anwendungsbeispiel |
|---|---|---|
| Cascade | Löscht alle zugehörigen Objekte | Auftrag zusammen mit Positionen löschen |
| Nullify | Setzt die inverse Beziehung auf null | Autor ohne Löschen der Bücher entfernen |
| Deny | Blockiert Löschung, wenn zugehörige Objekte existieren | Schutz vor Löschen einer Kategorie mit Produkten |
Die Wahl einer Delete Rule ist entscheidend für die Datenintegrität: Cascade kann ohne Überprüfung ein Drittel der Datenbank löschen, während Deny die Operation mit einem unklaren Fehler blockieren kann. Im Produktionscode wird Nullify mit manueller Behandlung verwaister Datensätze empfohlen.
Im Xcode-Modelleditor kann der Entwickler nicht nur Entities und Attribute definieren, sondern auch Constraints (eindeutige Beschränkungen), Indizes zur Abfragebeschleunigung und Standardwerte für Attribute. Alle Modelländerungen werden in eine .momd-Datei kompiliert, die bei der Initialisierung von NSPersistentContainer geladen wird. Die Modellversionierung (Model Versioning) ermöglicht die Verwaltung mehrerer Schema-Versionen und die Migration zwischen ihnen.
NSPersistentContainer ist ein einzelnes Objekt, das den Core Data Stack seit iOS 10 und macOS 10.12 verwaltet. Es kapselt NSManagedObjectModel, NSPersistentStoreCoordinator und NSManagedObjectContext und automatisiert das Laden des Modells und die Store-Konfiguration. Für ältere Versionen wurde der Stack manuell aufgebaut, was jedoch nicht mehr empfohlen wird.
let container = NSPersistentContainer(name: "DataModel")
container.loadPersistentStores { _, error in
if let error { fatalError("Core Data load failed: \(error)") }
}
let context = container.viewContext
viewContext ist der Hauptkontext, der an den Hauptthread gebunden ist. Alle Lese- und UI-Aktualisierungen werden über ihn durchgeführt. Für die Leistung wird empfohlen, das Schreiben von Daten in einem untergeordneten Hintergrundkontext mit anschließender Synchronisierung durchzuführen.
Der NSPersistentStoreCoordinator verbindet das Modell mit dem physischen Speicher auf der Festplatte. Core Data unterstützt mehrere Store-Typen: SQLite (empfohlen), Binary und In-Memory. Der SQLite-Store unterstützt Migrationen, inkrementelle Backups und Absturzsicherheit während Schreibvorgängen.
NSFetchRequest ist ein Objekt, das eine Abfrage an den Core Data Store beschreibt. Es enthält den Entity-Namen, das Filterprädikat, Sortierdeskriptoren und Fetch-Einstellungen. Die Abfrage wird über context.fetch() ausgeführt, das ein Array von NSManagedObject zurückgibt.
let request = NSFetchRequest<User>(entityName: "User")
request.predicate = NSPredicate(format: "age >= %d", 18)
request.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
request.fetchLimit = 50
let results = try context.fetch(request)
NSPredicate unterstützt komplexe Bedingungen: LIKE, IN, BETWEEN, CONTAINS[c] (Groß-/Kleinschreibung-unabhängig), SUBQUERY für verschachtelte Abfragen auf verbundenen Entities. Core Data unterstützt auch NSFetchedResultsController — eine Klasse zum reaktiven Laden von Daten in UITableView, die automatisch Änderungen verfolgt und die Tabelle mit animierten Abschnitten aktualisiert.
Die Arbeit mit Core Data in einer Multithread-Anwendung erfordert die strikte Einhaltung von Regeln: NSManagedObject kann nicht direkt zwischen Threads übergeben werden. Jeder Thread (oder jede Warteschlange) muss seinen eigenen Kontext verwenden. Der Hauptansatz ist die Erstellung eines untergeordneten NSManagedObjectContext mit einer privaten Warteschlange (NSPrivateQueueConcurrencyType) zum Schreiben und viewContext zum Lesen.
Der untergeordnete Kontext speichert im übergeordneten, und dann speichert der übergeordnete im Festplattenspeicher. Dadurch wird garantiert, dass Änderungen den Hauptthread nicht blockieren und die UI immer einen konsistenten Zustand durch mergeChanges oder automatische viewContext-Aktualisierung beim Speichern sieht.
Core Data verwendet faulting — einen verzögerten Lademechanismus für verwandte Objekte. Beim Abrufen eines User ohne Anforderung seiner Adressen werden die zugehörigen Address-Objekte nicht geladen, bis sie über die Punktnotation aufgerufen werden. Faulting spart Speicher und beschleunigt das Laden, kann aber zu unerwarteten Festplattenzugriffen auf dem Hauptthread führen, wenn der Zugriff in Hintergrundkontexten nicht kontrolliert wird.
Für effizientes Multithreading verwenden Sie NSBatchInsertRequest und NSBatchDeleteRequest für Masseneinfügungen und -löschungen ohne Laden von Objekten in den Speicher — dies ist entscheidend für die Datensynchronisation mit dem Server.
Batch-Operationen werden direkt auf der Ebene von NSPersistentStoreCoordinator ausgeführt, wobei Kontext und Objektgraph umgangen werden. Dies ermöglicht das Einfügen von 10.000 Datensätzen in Millisekunden, ohne 10.000 NSManagedObject-Instanzen im Speicher zu erzeugen. Nach der Ausführung einer Batch-Anforderung muss der Kontext über mergeChangesFromContextDidSaveNotification aktualisiert werden, damit die UI die neuen Daten anzeigt. Apple empfiehlt Batch-Operationen für das anfängliche Laden von Daten und die nächtliche Serversynchronisation.
Zur Änderungsverfolgung in Core Data wird NSPersistentHistoryTracking verwendet — ein Mechanismus, der jede Transaktion (Einfügen, Aktualisieren, Löschen) in einem separaten Verlauf aufzeichnet. Die Aktivierung der Verlaufsverfolgung ermöglicht die Datensynchronisation zwischen verschiedenen Prozessen und Anwendungen, die mit derselben SQLite-Datei arbeiten, z.B. zwischen der Hauptanwendung und einer Notification Service Extension. Die Aktivierung erfolgt über NSPersistentStoreDescription mit dem Flag persistentHistoryTrackingKey und das Lesen über NSPersistentHistoryChangeRequest mit Filterung nach Datum und Transaktionstyp.
Zum Debuggen und zur Leistungsprofilierung von Core Data wird das Core Data Profiler-Tool aus der Instruments-Suite in Xcode unter macOS verwendet. Es zeigt alle Fetch-, Insert-, Delete- und Save-Operationen mit der Dauer jeder Operation und der Anzahl der geladenen Objekte in Tabellen und Zeitachsendiagrammen an. Der Entwickler kann Problembereiche identifizieren: mehrere Abrufe derselben Abfrage (fehlende Zwischenspeicherung), Fault-Objektlecks beim Tabellenscrollen oder Hauptthread-Blockierung durch synchrones Laden verwandter Entitäten. Es wird empfohlen, das Profiling auf einem echten Gerät und nicht auf dem Simulator durchzuführen, da die Leistung des Simulators nicht das tatsächliche Verhalten der Anwendung auf einem iPhone oder iPad widerspiegelt.
Häufig gestellte Fragen
Core Data ist keine Datenbank, sondern eine Objektverwaltungsschicht, die SQLite als Speicher verwenden kann. Im Gegensatz zu rohem SQLite verfolgt Core Data Objektänderungen, verwaltet Rückgängig-Funktionen und stellt einen Objektgraphen mit Faulting und Caching bereit. SQLite bietet mehr Kontrolle über Abfragen, erfordert jedoch das Schreiben von SQL und die manuelle Verwaltung von Transaktionen.
Core Data unterstützt Lightweight Migration für nicht-destruktive Änderungen: Hinzufügen eines Attributs, Umbenennen, Festlegen eines Standardwerts. Für komplexe Änderungen wird ein Mapping Model erstellt. Die Lightweight-Migration wird durch das Flag shouldMigrateAutomatically in NSPersistentStoreDescription aktiviert.
Ja, Core Data integriert sich mit SwiftUI über den @FetchRequest-Wrapper für Abfragen und @ObservedObject für Änderungsabonnements. SwiftUI aktualisiert die View automatisch, wenn sich ein ManagedObject ändert, was Core Data und SwiftUI zu einem kompatiblen Stack für die Zustandsverwaltung macht.
Ein Fault ist ein leichter Platzhalter im Core Data-Graphen, der keine Daten des zugehörigen Objekts enthält. Wenn ein Fault gesetzt wird (über refreshObject:), werden die Daten aus dem Speicher entladen. Beim Zugriff auf eine Eigenschaft wird der Fault automatisch mit Daten aus dem Speicher gefüllt — dies ist ein verzögerter Lademechanismus, der die Speichernutzung optimiert.
Für Tests verwenden Sie den In-Memory-Speichertyp: NSPersistentStoreDescription mit NSInMemoryStoreType. Der Container wird mit dem Modell aus dem Test-Bundle erstellt. Nach jedem Test löschen Sie alle Objekte oder erstellen den Container neu — dies garantiert die Isolation der Testfälle voneinander.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch