Swift
Core Data
Data Deletion
iOS Development
App Programming

Delete ALL Core Data Swift

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Deleting all Core Data content can mean two different things: removing every managed object, or destroying the persistent store and rebuilding it. Those operations solve different problems, so the safest implementation starts by deciding whether you want a data reset or a full storage reset.

Delete Records While Keeping the Store

For most app features, such as a sign-out flow or a debug "clear local data" button, you want to keep the store and delete the records. NSBatchDeleteRequest is the right tool because it works directly against SQLite instead of loading every object into memory.

swift
1import CoreData
2
3func deleteAllObjects(in container: NSPersistentContainer) throws {
4    let context = container.viewContext
5
6    for entity in container.managedObjectModel.entities {
7        guard let name = entity.name else { continue }
8
9        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: name)
10        let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
11        deleteRequest.resultType = .resultTypeObjectIDs
12
13        let result = try context.execute(deleteRequest) as? NSBatchDeleteResult
14        let deletedIDs = result?.result as? [NSManagedObjectID] ?? []
15
16        let changes: [AnyHashable: Any] = [NSDeletedObjectsKey: deletedIDs]
17        NSManagedObjectContext.mergeChanges(
18            fromRemoteContextSave: changes,
19            into: [context]
20        )
21    }
22}

The merge step is not optional in a real app. Batch deletes bypass existing managed objects, so views backed by FetchedResultsController, SwiftUI fetch requests, or cached object references can otherwise keep showing stale rows.

When a Full Store Reset Is Better

If you are fixing a broken development database, resetting integration tests, or clearing incompatible on-device state after a schema experiment, destroying the persistent store may be simpler than deleting every entity. That resets the SQLite file and its companion files in one step.

swift
1import CoreData
2
3final class PersistenceController {
4    let container: NSPersistentContainer
5
6    init(name: String) {
7        container = NSPersistentContainer(name: name)
8        container.loadPersistentStores { _, error in
9            if let error = error {
10                fatalError("Failed to load store: \(error)")
11            }
12        }
13    }
14
15    func resetStore() throws {
16        guard let store = container.persistentStoreCoordinator.persistentStores.first,
17              let url = store.url else {
18            return
19        }
20
21        let coordinator = container.persistentStoreCoordinator
22        try coordinator.destroyPersistentStore(
23            at: url,
24            ofType: NSSQLiteStoreType,
25            options: nil
26        )
27
28        try coordinator.addPersistentStore(
29            ofType: NSSQLiteStoreType,
30            configurationName: nil,
31            at: url,
32            options: nil
33        )
34    }
35}

This approach is more disruptive. Any existing managed object contexts, fetched objects, or in-memory references associated with the old store should be discarded and recreated.

Choosing Between the Two

A useful rule is to ask what should remain stable after the operation.

  • If the app should keep the same Core Data stack and just lose its rows, use batch delete.
  • If the store itself is corrupt, obsolete, or only used for testing, rebuild the store.

For production code, record deletion is usually easier to reason about because the persistent container stays intact. For development tools, destroying the store may produce a cleaner reset with less entity-specific code.

A Small End-to-End Example

The next example shows a reset function for a signed-in user. It deletes Core Data rows and then refreshes the UI on the main actor.

swift
1import CoreData
2import Foundation
3
4@MainActor
5func clearLocalUserData(container: NSPersistentContainer) async {
6    do {
7        try deleteAllObjects(in: container)
8        try container.viewContext.save()
9    } catch {
10        print("Failed to clear data: \(error)")
11    }
12}

The save call here does not perform the deletion itself. It is still useful when other pending context changes should be flushed after the reset. In larger apps, you would also recreate background contexts or invalidate caches owned by repositories and view models.

Common Pitfalls

  • Deleting rows with NSBatchDeleteRequest and forgetting to merge deleted object IDs back into active contexts.
  • Fetching every object and calling delete in a loop for large tables, which is slower and uses more memory.
  • Destroying the store in production code when only app data needed to be cleared.
  • Keeping old NSManagedObject references after a full store reset.
  • Clearing Core Data but forgetting related app state such as image caches, in-memory sessions, or background workers.

Summary

  • "Delete all Core Data" can mean deleting records or rebuilding the store.
  • 'NSBatchDeleteRequest is the normal choice when you want to keep the store and remove all rows.'
  • A store reset is useful for tests and broken development databases, but it invalidates existing contexts.
  • UI and cache refresh logic matters as much as the deletion call itself.
  • Pick the least disruptive reset that matches the real problem.

Course illustration
Course illustration

All Rights Reserved.