In some cases when using Core Data in iOS and macOS apps more than one entity needs to be deleted. This post presents various examples of deleting multiple entities in Core Data with Swift:
- Delete Multiple Objects
- Delete Object With Relationship (Cascade Delete Rule)
- Delete Relationship Objects
- Delete Objects With Predicate
- Batch Delete
- Delete Everything (Delete All Objects, Reset Core Data)
Note: in this post persistentContainer
will be used to refer to an initialized instance of NSPersistentContainer
, and object will be used to refer to an initialized instance of NSManagedObject
.
Delete Multiple Objects
One way to delete multiple objects in Core Data is to call delete(_:)
on a NSManagedObjectContext
for each NSManagedObject
to delete, and then save the NSManagedObjectContext
:
// List of multiple objects to delete
let objects: [NSManagedObject] = // A list of objects
// Get a reference to a managed object context
let context = persistentContainer.viewContext
// Delete multiple objects
for object in objects {
context.delete(object)
}
// Save the deletions to the persistent store
try context.save()
Delete Object With Relationship (Cascade Delete Rule)
A Delete Rule defines what happens to relationship objects when an object is deleted, and a Cascade Delete Rule will delete relationship objects automatically when the parent object is deleted.
Set a Delete Rule on Entity Relationships inside of the Core Data Entity Inspector in Xcode:
A Delete Rule will only take effect and consider relationships when an object is deleted. Setting a relationship to nil
like object.items = nil
or removing objects from a relationship will not trigger a Delete Rule.
Only deleting the parent object will trigger a Cascade Delete Rule:
let object = // An NSManagedObject
// Get a reference to a managed object context
let context = persistentContainer.viewContext
// Delete the object with a relationship. Calling
// delete(_:) will trigger the Delete Rules for
// object relationships
try context.delete(object)
// Save the deletions to the persistent store
try context.save()
Delete Relationship Objects
To delete relationship objects where a Cascade delete rule is not specified delete each relationship object individually then save the NSManagedObjectContext
:
let object = // An NSManagedObject with a
// relationship called items
// Get a reference to a managed object context
let context = persistentContainer.viewContext
// Delete each related entity
for entity in object.items ?? [] {
try context.delete(entity as? NSManagedObject)
}
// Save the deletions to the persistent store
try context.save()
Delete Objects With Predicate
Like deleting multiple objects in Core Data using delete(_:)
, delete objects with a predicate in Core Data by getting objects from a fetch request, deleting those objects, and then saving the NSManagedObjectContext
:
// Create a fetch request with a predicate
let fetchRequest: NSFetchRequest<Business>
fetchRequest = Business.fetchRequest()
fetchRequest.predicate = // an NSPredicate
// Setting includesPropertyValues to false means
// the fetch request will only get the managed
// object ID for each object
fetchRequest.includesPropertyValues = false
// Get a reference to a managed object context
let context = persistentContainer.viewContext
// Perform the fetch request
let objects = try context.fetch(fetchRequest)
// Delete the objects
for object in objects {
context.delete(object)
}
// Save the deletions to the persistent store
try context.save()
You can see more examples of fetch requests with predicates in the following article:
Batch Delete
Calling delete(_:)
for each individual NSManagedObject
may take time if there are many objects to delete. A faster approach to batch delete objects in Core Data is NSBatchDeleteRequest
.
Some important considerations when using NSBatchDeleteRequest
are:
NSBatchDeleteRequest
directly modifies theNSPersistentStore
without loading any data into memory.- An
NSBatchDeleteRequest
does not modify anNSManagedObjectContext
. UsemergeChanges(fromRemoteContextSave:, into:)
as shown in the example if needed to inform aNSManagedObjectContext
of the batch delete.
// Specify a batch to delete with a fetch request
let fetchRequest: NSFetchRequest<NSFetchRequestResult>
fetchRequest = NSFetchRequest(entityName: "Business")
// Create a batch delete request for the
// fetch request
let deleteRequest = NSBatchDeleteRequest(
fetchRequest: fetchRequest
)
// Specify the result of the NSBatchDeleteRequest
// should be the NSManagedObject IDs for the
// deleted objects
deleteRequest.resultType = .resultTypeObjectIDs
// Get a reference to a managed object context
let context = persistentContainer.viewContext
// Perform the batch delete
let batchDelete = try context.execute(deleteRequest)
as? NSBatchDeleteResult
guard let deleteResult = batchDelete?.result
as? [NSManagedObjectID]
else { return }
let deletedObjects: [AnyHashable: Any] = [
NSDeletedObjectsKey: deleteResult
]
// Merge the delete changes into the managed
// object context
NSManagedObjectContext.mergeChanges(
fromRemoteContextSave: deletedObjects,
into: [context]
)
Delete Everything (Delete All Objects, Reset Core Data)
One approach to delete everything and reset Core Data is to destroy the persistent store. Deleting and re-creating the persistent store will delete all objects in Core Data.
An important consideration when deleting everything in Core Data, make sure to release and re-initialize existing NSManagedObjectContext
references. Using a NSManagedObjectContext
backed by a deleted persistent store may have unexpected behavior.
// Get a reference to a NSPersistentStoreCoordinator
let storeContainer =
persistentContainer.persistentStoreCoordinator
// Delete each existing persistent store
for store in storeContainer.persistentStores {
try storeContainer.destroyPersistentStore(
at: store.url!,
ofType: store.type,
options: nil
)
}
// Re-create the persistent container
persistentContainer = NSPersistentContainer(
name: "CoreDataModelFile" // the name of
// a .xcdatamodeld file
)
// Calling loadPersistentStores will re-create the
// persistent stores
persistentContainer.loadPersistentStores {
(store, error) in
// Handle errors
}
Batch Delete Core Data Objects in Swift
That's it! By using fetch requests, batch delete requests, managed object contexts, and persistent stores you can delete multiple objects and delete everything in Core Data using Swift.