Core Data vs SwiftData Comparison

Apple's battle-tested persistence framework, mature over 20 years

VS
SwiftData

WWDC 2023: Swift-native persistence with zero boilerplate via the @Model macro

8 min readiOS

Quick Verdict

If you're targeting iOS 17+, start with SwiftData — less code, fewer bugs, better SwiftUI integration. Choose Core Data if you need support for older devices, complex migrations, or already have a large production Core Data codebase. Since both share the same underlying infrastructure, they can theoretically be used together.

Core DataSwiftData
Read the full verdict

Score Comparison

Loading chart...

Detailed Scoring

Detailed Scoring: Core Data and SwiftData — category-by-category scores out of 10
CategoryCore DataSwiftData
Performance
9/10
9/10
Ease of Learning
4/10
9/10
Ecosystem
9/10
6/10
Community
9/10
5/10
Job Market
8/10
6/10
Future-Proof
6/10
10/10

Pros & Cons

Core Data

Pros

  • Available since iOS 3 — extremely stable and well documented
  • Excellent NSFetchedResultsController integration with UITableView/UICollectionView
  • iCloud sync via NSPersistentCloudKitContainer for cloud synchronization
  • Mature support for complex relationship and migration scenarios
  • Advanced tuning features such as faulting and batch operations
  • Core Spotlight integration makes content searchable
  • SQLite, Binary, and In-Memory store types
  • Broad community knowledge and Stack Overflow resources

Cons

  • Verbose code with NSManagedObject — a lot of boilerplate
  • Thread safety is tricky — correctly managing NSManagedObjectContext is complex
  • Steep learning curve — NSFetchRequest and NSPredicate syntax
  • Error messages aren't very helpful to developers
  • Requires a wrapper to work comfortably with modern Swift

Best For

Apps that need to support below iOS 16Complex data relationships and migration requirementsApps where iCloud sync is criticalLarge datasets and advanced fetch optimizationMaintaining existing Core Data projects

SwiftData

Pros

  • One-line data model definitions with the @Model macro — zero boilerplate
  • Native SwiftUI integration — @Query automatically updates the UI
  • Compatible with Swift Concurrency — works naturally with async/await
  • Built on top of Core Data — same SQLite infrastructure, same performance
  • Far simpler iCloud sync configuration
  • Type-safe predicates and sort descriptors
  • Minimal migration API — simple schema changes happen automatically

Cons

  • Requires iOS 17+ — still early for widespread adoption
  • Less control than Core Data in complex migration scenarios
  • Still maturing — major changes can arrive with every WWDC
  • Far fewer Stack Overflow/community resources than Core Data
  • Some advanced Core Data features don't yet have an equivalent

Best For

New projects targeting iOS 17+SwiftUI apps needing persistence integrationSimple-to-moderate complexity data modelsRapid prototyping and small appsModern Swift teams starting new projects

Code Comparison

Core Data
// Core Data - Todo list CRUD
import CoreData
import SwiftUI

// NSManagedObject subclass
@objc(TodoItem)
class TodoItem: NSManagedObject {
    @NSManaged var id: UUID
    @NSManaged var title: String
    @NSManaged var isCompleted: Bool
    @NSManaged var createdAt: Date
}

// View Model
class TodoViewModel: ObservableObject {
    let container: NSPersistentContainer
    @Published var todos: [TodoItem] = []

    init() {
        container = NSPersistentContainer(name: "TodoModel")
        container.loadPersistentStores { _, error in
            if let error { fatalError("Core Data load failed: \\(error)") }
        }
        fetchTodos()
    }

    func fetchTodos() {
        let request = NSFetchRequest<TodoItem>(entityName: "TodoItem")
        request.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: false)]
        do {
            todos = try container.viewContext.fetch(request)
        } catch {
            print("Fetch error: \\(error)")
        }
    }

    func addTodo(title: String) {
        let todo = TodoItem(context: container.viewContext)
        todo.id = UUID()
        todo.title = title
        todo.isCompleted = false
        todo.createdAt = Date()
        saveContext()
    }

    func toggleTodo(_ todo: TodoItem) {
        todo.isCompleted.toggle()
        saveContext()
    }

    private func saveContext() {
        try? container.viewContext.save()
        fetchTodos()
    }
}
SwiftData
// SwiftData - Todo list CRUD
import SwiftData
import SwiftUI

// @Model macro — no boilerplate!
@Model
class TodoItem {
    var id: UUID
    var title: String
    var isCompleted: Bool
    var createdAt: Date

    init(title: String) {
        self.id = UUID()
        self.title = title
        self.isCompleted = false
        self.createdAt = Date()
    }
}

// SwiftUI View — @Query auto-updates
struct TodoListView: View {
    @Environment(\\.modelContext) private var context
    @Query(sort: \\.createdAt, order: .reverse) private var todos: [TodoItem]
    @State private var newTitle = ""

    var body: some View {
        List {
            ForEach(todos) { todo in
                HStack {
                    Image(systemName: todo.isCompleted ? "checkmark.circle.fill" : "circle")
                        .foregroundStyle(todo.isCompleted ? .green : .gray)
                        .onTapGesture { todo.isCompleted.toggle() }
                    Text(todo.title)
                        .strikethrough(todo.isCompleted)
                }
            }
            .onDelete { indexSet in
                indexSet.forEach { context.delete(todos[$0]) }
            }
        }
        .toolbar {
            TextField("New todo...", text: $newTitle)
            Button("Add") {
                guard !newTitle.isEmpty else { return }
                context.insert(TodoItem(title: newTitle))
                newTitle = ""
            }
        }
    }
}

Conclusion

If you're targeting iOS 17+, start with SwiftData — less code, fewer bugs, better SwiftUI integration. Choose Core Data if you need support for older devices, complex migrations, or already have a large production Core Data codebase. Since both share the same underlying infrastructure, they can theoretically be used together.

Get Free Consultation
FAQ

Frequently Asked Questions

In the long run, yes — that's the direction of Apple's investment. But phasing out Core Data will take years; existing Core Data projects will continue to be supported.

Related Blog Posts

View All Posts

Related Projects

View All Projects
All Comparisons