Core Data — co to jest, model danych i jak działa

Autor: IT Sectr Opublikowano: 2026-05-04 Czas czytania: 8 min

Core Data to framework do zarządzania danymi od Apple, zapewniający mapowanie obiektowo-relacyjne dla iOS, macOS, tvOS i watchOS. Automatyzuje zapisywanie, pobieranie i filtrowanie obiektów w aplikacji, działając na SQLite, XML lub binarnym magazynie. Według Apple Core Data Documentation, framework wykorzystuje koncepcje Managed Object Context i NSPersistentContainer do zarządzania stosem trwałości.

Najważniejsze

  • Core Data — framework Apple do obiektowo-relacyjnego zarządzania danymi w aplikacjach.
  • NSManagedObjectModel — opis schematu danych: Entity, Attributes i Relationships.
  • NSManagedObject — obiekt odpowiadający jednemu rekordowi w magazynie Core Data.
  • NSManagedObjectContext — obszar roboczy do tworzenia, odczytu i zapisywania obiektów.
  • NSPersistentContainer — jednolity stos łączący model, kontekst i koordynator magazynu.

Czym jest Core Data i jego rola w iOS

Core Data — to framework do zarządzania grafem obiektów i trwałością, wchodzący w skład Cocoa Touch. Wbrew powszechnemu przekonaniu, Core Data nie jest bazą danych, lecz warstwą zarządzania obiektami, która może używać SQLite jako jednego z magazynów. Głównym zadaniem Core Data jest śledzenie zmian obiektów, zarządzanie ich cyklem życia i synchronizacja stanu z dyskiem.

Framework zapewnia graf obiektów, gdzie każdy Managed Object jest śledzony przez kontekst pod kątem zmian. Przy zapisie kontekstu wszystkie zmodyfikowane, dodane i usunięte obiekty są zatwierdzane w trwałym magazynie jedną transakcją. To uwalnia programistę od pisania zapytań SQL i ręcznego zarządzania transakcjami.

Według statystyk Swift Developer Survey (2025), Core Data jest używany w 52% aplikacji iOS pracujących z danymi lokalnymi. Pomimo pojawienia się nowoczesnych alternatyw (SwiftData, Realm), Core Data pozostaje głównym frameworkiem w istniejących projektach Apple dzięki dojrzałości i głębokiej integracji z systemem.

Używaj Core Data do projektów o średnio złożonym modelu danych, gdzie potrzebne są relacje między obiektami, wycofywanie zmian i automatyczne buforowanie przez mechanizm faulting.

Architektura Core Data zbudowana jest wokół koncepcji Managed Object Context — obszaru roboczego, który śledzi wszystkie zmiany obiektów. Kontekst obsługuje wycofywanie (undo/redo) przez wbudowany NSUndoManager, co pozwala na implementację wersji roboczych i anulowanie działań bez ręcznego zapisywania snapshotów stanu. Przy wywołaniu save() kontekst zatwierdza wszystkie zmiany jedną transakcją w trwałym magazynie, gwarantując atomowość i spójność danych.

Model danych: Entity, Attributes, Relationships

Model danych Core Data jest definiowany w pliku .xcdatamodeld — wizualnym edytorze Xcode, gdzie opisuje się wszystkie Entity, ich atrybuty i relacje. Podczas kompilacji model jest serializowany do .momd i ładowany przez NSManagedObjectModel.

Entity i Attributes

Entity — to opis typu danych, analogiczny do tabeli w SQL. Każde Entity zawiera zestaw Attributes — nazwanych pól z typem danych (String, Integer, Date, Boolean, Data). W przeciwieństwie do Room, Core Data wymaga jawnego wyboru typu dla każdego atrybutu przez edytor modelu.

Relationships

Relationship — relacja między Entity, analogiczna do klucza obcego w SQL. Core Data obsługuje wszystkie typy relacji: jeden-do-jednego, jeden-do-wielu i wiele-do-wielu. Dla każdej relacji konfiguruje się Delete Rule (Cascade, Nullify, Deny) — zachowanie przy usuwaniu powiązanego obiektu.

Delete RuleZachowanie przy usuwaniuPrzykład zastosowania
CascadeUsuwa wszystkie powiązane obiektyUsunięcie zamówienia wraz z pozycjami
NullifyZeruje odwrotne powiązanieUsunięcie autora bez usuwania książek
DenyBlokuje usunięcie, jeśli istnieją powiązane obiektyOchrona przed usunięciem kategorii z produktami

Wybór Delete Rule jest krytyczny dla integralności danych: Cascade bez sprawdzenia może usunąć jedną trzecią bazy, a Deny — zablokować operację z niezrozumiałym błędem. W kodzie produkcyjnym zaleca się Nullify z ręcznym przetwarzaniem osieroconych rekordów.

W edytorze modelu Xcode programista może ustawiać nie tylko Entity i atrybuty, ale także constraints (ograniczenia unikalności), indeksy dla przyspieszenia zapytań i default values dla atrybutów. Wszystkie zmiany modelu są kompilowane do pliku .momd, który jest ładowany podczas inicjalizacji NSPersistentContainer. Wersjonowanie modelu (Model Versioning) pozwala utrzymywać wiele wersji schematu i wykonywać migrację między nimi.

Stos Core Data: PersistentContainer i Context

NSPersistentContainer — jednolity obiekt zarządzający stosem Core Data od iOS 10 i macOS 10.12. Hermetyzuje NSManagedObjectModel, NSPersistentStoreCoordinator i NSManagedObjectContext, automatyzując ładowanie modelu i konfigurację magazynu. Dla starszych wersji stos był budowany ręcznie, ale obecnie nie jest to zalecane.

swift
let container = NSPersistentContainer(name: "DataModel")
container.loadPersistentStores { _, error in
    if let error { fatalError("Core Data load failed: \(error)") }
}
let context = container.viewContext

viewContext — główny kontekst powiązany z głównym wątkiem. Wszystkie odczyty i aktualizacje UI są wykonywane przez niego. Zapis danych dla wydajności zaleca się wykonywać w kontekście potomnym z prywatną kolejką i późniejszą synchronizacją.

NSPersistentStoreCoordinator

Koordynator NSPersistentStoreCoordinator łączy model z fizycznym magazynem na dysku. Core Data obsługuje kilka typów magazynów: SQLite (zalecany), Binary i In-Memory. Magazyn SQLite obsługuje migracje, przyrostowe kopie zapasowe i odporność na awarie podczas zapisu.

NSFetchRequest i praca z danymi

NSFetchRequest — obiekt opisujący zapytanie do magazynu Core Data. Zawiera nazwę Entity, predykat filtrowania, sortowanie i ustawienia pobierania. Zapytanie jest wykonywane przez context.fetch(), który zwraca tablicę NSManagedObject.

swift
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 obsługuje złożone warunki: LIKE, IN, BETWEEN, CONTAINS[c] (bez rozróżniania wielkości liter), SUBQUERY dla zagnieżdżonych zapytań po powiązanych Entity. Core Data obsługuje również NSFetchedResultsController — klasę do reaktywnego ładowania danych w UITableView, która automatycznie śledzi zmiany i aktualizuje tabelę z animacjami sekcji.

Core Data w środowisku wielowątkowym

Praca z Core Data w aplikacji wielowątkowej wymaga ścisłego przestrzegania zasad: NSManagedObject nie może być przekazywany między wątkami bezpośrednio. Każdy wątek (lub kolejka) powinien używać własnego kontekstu. Podstawowym podejściem jest utworzenie potomnego NSManagedObjectContext z prywatną kolejką (NSPrivateQueueConcurrencyType) do zapisu i viewContext do odczytu.

Kontekst potomny zapisuje do nadrzędnego, a nadrzędny — do magazynu na dysku. Gwarantuje to, że zmiany nie blokują głównego wątku i że UI zawsze widzi spójny stan przez mergeChanges lub automatyczną aktualizację viewContext przy zapisie.

Core Data używa faultingu — mechanizmu opóźnionego ładowania powiązanych obiektów. Podczas pobierania User bez żądania jego addresses, powiązane Address nie są ładowane, dopóki nie nastąpi do nich odwołanie przez notację kropkową. Faulting oszczędza pamięć i przyspiesza ładowanie, ale może powodować nieoczekiwane odwołania do dysku na głównym wątku, jeśli nie kontroluje się dostępu w kontekstach tła.

Dla efektywnej wielowątkowości używaj NSBatchInsertRequest i NSBatchDeleteRequest do masowego wstawiania i usuwania bez ładowania obiektów do pamięci — jest to krytyczne dla synchronizacji danych z serwerem.

Operacje batch są wykonywane bezpośrednio na poziomie NSPersistentStoreCoordinator, omijając kontekst i graf obiektów. Pozwala to wstawić 10 000 rekordów w kilka milisekund bez tworzenia 10 000 instancji NSManagedObject w pamięci. Po wykonaniu zapytania batch kontekst należy odświeżyć przez mergeChangesFromContextDidSaveNotification, aby UI odzwierciedliło nowe dane. Apple zaleca operacje batch do początkowego ładowania danych i nocnej synchronizacji z serwerem.

Do śledzenia zmian w Core Data używa się NSPersistentHistoryTracking — mechanizmu rejestrującego każdą transakcję (wstawienie, aktualizację, usunięcie) w osobnej historii. Włączenie history tracking pozwala synchronizować dane między różnymi procesami i aplikacjami pracującymi z jednym plikiem SQLite, na przykład między główną aplikacją a Notification Service Extension. Aktywacja odbywa się przez NSPersistentStoreDescription z flagą persistentHistoryTrackingKey, a odczyt — przez NSPersistentHistoryChangeRequest z filtrem po dacie i typie transakcji.

Do debugowania i profilowania wydajności Core Data używa się narzędzia Core Data Profiler z zestawu Instruments w Xcode na macOS. Pokazuje ono wszystkie operacje pobierania, wstawiania, usuwania i zapisywania z czasem trwania każdej operacji i liczbą załadowanych obiektów w tabelach i na wykresach osi czasu. Programista może zidentyfikować problematyczne obszary: wielokrotne pobieranie tego samego zapytania (brak buforowania), wycieki obiektów fault podczas przewijania tabeli lub blokowanie głównego wątku z powodu synchronicznego ładowania powiązanych encji. Zaleca się uruchamianie profilowania na rzeczywistym urządzeniu, a nie na symulatorze, ponieważ wydajność symulatora nie odzwierciedla rzeczywistego zachowania aplikacji na iPhone lub iPad.

Często zadawane pytania

Czym Core Data różni się od SQLite?

Core Data — to nie baza danych, ale warstwa zarządzania obiektami, która może używać SQLite jako magazynu. W przeciwieństwie do bezpośredniego SQLite, Core Data śledzi zmiany obiektów, zarządza wycofywaniem i zapewnia graf obiektów z faultingiem i buforowaniem. SQLite daje większą kontrolę nad zapytaniami, ale wymaga pisania SQL i ręcznego zarządzania transakcjami.

Jak wykonać migrację schematu Core Data?

Core Data obsługuje lekką migrację (Lightweight Migration) dla nieniszczących zmian: dodanie atrybutu, zmiana nazwy, ustawienie wartości domyślnej. Dla złożonych zmian tworzy się Mapping Model. Lekka migracja jest włączana flagą shouldMigrateAutomatically w NSPersistentStoreDescription.

Czy można używać Core Data z SwiftUI?

Tak, Core Data integruje się ze SwiftUI przez otokę @FetchRequest dla zapytań i @ObservedObject do subskrypcji zmian. SwiftUI automatycznie aktualizuje View przy zmianie ManagedObject, co czyni Core Data i SwiftUI kompatybilnym stosem do zarządzania stanem.

Czym jest fault w Core Data?

Fault — to lekka zaślepka w grafie Core Data, niezawierająca danych powiązanego obiektu. Przy ustawieniu fault (przez refreshObject:) dane są zwalniane z pamięci. Przy odwołaniu do właściwości fault automatycznie wypełnia się danymi z magazynu — jest to mechanizm opóźnionego ładowania, optymalizujący użycie pamięci.

Jak testować kod Core Data?

Do testowania używaj typu magazynu In-Memory: NSPersistentStoreDescription z NSInMemoryStoreType. Kontener tworzy się z modelem z pakietu testowego. Po każdym teście usuwaj wszystkie obiekty lub odtwarzaj kontener — gwarantuje to izolację przypadków testowych od siebie.

Podsumowanie

  • Core Data — framework do zarządzania grafem obiektów, używający SQLite jako domyślnego magazynu.
  • NSManagedObjectModel opisuje schemat: Entity, Attributes, Relationships i Delete Rules.
  • NSPersistentContainer łączy model, koordynator i viewContext w jednolity stos.
  • NSFetchRequest z NSPredicate i NSSortDescriptor tworzy elastyczne zapytania do magazynu.
  • Wielowątkowość wymaga oddzielnych kontekstów: potomny kontekst do zapisu i viewContext do odczytu.
  • Faulting opóźnia ładowanie powiązanych obiektów do pierwszego odwołania, oszczędzając pamięć.
  • Lightweight Migration automatycznie obsługuje nieniszczące zmiany schematu bez utraty danych.

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również