iOS: Delete ALL Core Data Swift
IosSwiftCore DataIos Problem Overview
I am a little confused as to how to delete all core data in swift. I have created a button with an IBAction
linked. On the click of the button I have the following:
let appDel: foodforteethAppDelegate = UIApplication.sharedApplication().delegate as foodforteethAppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext
Then I've messed around with various methods to try and delete all the core data content but I can't seem to get it to work. I've used removeAll to delete from a stored array but still can't delete from the core data. I assume I need some type of for loop but unsure how to go about making it from the request.
I have tried applying the basic principle of deleting a single row
func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!) {
let appDel: foodforteethAppDelegate = UIApplication.sharedApplication().delegate as foodforteethAppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext
if editingStyle == UITableViewCellEditingStyle.Delete {
if let tv = tblTasks {
context.deleteObject(myList[indexPath!.row] as NSManagedObject)
myList.removeAtIndex(indexPath!.row)
tv.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: UITableViewRowAnimation.Fade)
}
var error: NSError? = nil
if !context.save(&error) {
abort()
}
}
}
However, the issue with this is that when I click a button, I don't have the indexPath value and also I need to loop through all the values which I can't seem to do with context.
Ios Solutions
Solution 1 - Ios
Try this simple solution:
func deleteAllData(entity: String)
{
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let fetchRequest = NSFetchRequest(entityName: entity)
fetchRequest.returnsObjectsAsFaults = false
do
{
let results = try managedContext.executeFetchRequest(fetchRequest)
for managedObject in results
{
let managedObjectData:NSManagedObject = managedObject as! NSManagedObject
managedContext.deleteObject(managedObjectData)
}
} catch let error as NSError {
print("Detele all data in \(entity) error : \(error) \(error.userInfo)")
}
}
Swift 4
func deleteAllData(_ entity:String) {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
fetchRequest.returnsObjectsAsFaults = false
do {
let results = try dataController.viewContext.fetch(fetchRequest)
for object in results {
guard let objectData = object as? NSManagedObject else {continue}
dataController.viewContext.delete(objectData)
}
} catch let error {
print("Detele all data in \(entity) error :", error)
}
}
Implementation:
self.deleteAllData("your_entityName")
Solution 2 - Ios
You can use destroyPersistentStore
starting in iOS 9.0 and Swift 3:
public func clearDatabase() {
guard let url = persistentContainer.persistentStoreDescriptions.first?.url else { return }
let persistentStoreCoordinator = persistentContainer.persistentStoreCoordinator
do {
try persistentStoreCoordinator.destroyPersistentStore(at:url, ofType: NSSQLiteStoreType, options: nil)
try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
} catch {
print("Attempted to clear persistent store: " + error.localizedDescription)
}
}
Solution 3 - Ios
To Delete all data you can use NSBatchDeleteRequest
func deleteAllData(entity: String)
{
let ReqVar = NSFetchRequest(entityName: entity)
let DelAllReqVar = NSBatchDeleteRequest(fetchRequest: ReqVar)
do { try ContxtVar.executeRequest(DelAllReqVar) }
catch { print(error) }
}
Solution 4 - Ios
I have got it working using the following method:
@IBAction func btnDelTask_Click(sender: UIButton){
let appDel: foodforteethAppDelegate = UIApplication.sharedApplication().delegate as foodforteethAppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext
let request = NSFetchRequest(entityName: "Food")
myList = context.executeFetchRequest(request, error: nil)
if let tv = tblTasks {
var bas: NSManagedObject!
for bas: AnyObject in myList
{
context.deleteObject(bas as NSManagedObject)
}
myList.removeAll(keepCapacity: false)
tv.reloadData()
context.save(nil)
}
}
However, I am unsure whether this is the best way to go about doing it. I'm also receiving a 'constant 'bas' inferred to have anyobject' error - so if there are any solutions for that then it would be great
EDIT
Fixed by changing to bas: AnyObject
Solution 5 - Ios
For Swift 3.0
func DeleteAllData(){
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
let DelAllReqVar = NSBatchDeleteRequest(fetchRequest: NSFetchRequest<NSFetchRequestResult>(entityName: "Entity"))
do {
try managedContext.execute(DelAllReqVar)
}
catch {
print(error)
}
}
Solution 6 - Ios
Here is my implementation to clear all core data in Swift 3, based on Jayant Dash's excellent (and comprehensive) answer. This is simpler due to only supporting iOS10+. It deletes all core data entities, without having to hardcode them.
public func clearAllCoreData() {
let entities = self.persistentContainer.managedObjectModel.entities
entities.flatMap({ $0.name }).forEach(clearDeepObjectEntity)
}
private func clearDeepObjectEntity(_ entity: String) {
let context = self.persistentContainer.viewContext
let deleteFetch = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)
do {
try context.execute(deleteRequest)
try context.save()
} catch {
print ("There was an error")
}
}
Solution 7 - Ios
Swift 5.1
Most of the posts here suggests to create a function to delete all entities by name and then delete all your entities by name. like so :
resetEntity(named: "MyEntity1")
resetEntity(named: "MyEntity2")
resetEntity(named: "MyEntity3")
...
But if the real question is how to clean ALL CoreData entity in one go, I suggest you loop over entity names:
// Supposing this is a CoreDataController/CoreDataStack class where you have access to `viewContext` and `persistantContainer`
// Otherwise just pass the `persistantContainer` as a parameter, from which you can also retrieve the `viewContext`
func resetAllCoreData() {
// get all entities and loop over them
let entityNames = self.persistentContainer.managedObjectModel.entities.map({ $0.name!})
entityNames.forEach { [weak self] entityName in
let deleteFetch = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)
do {
try self?.context.execute(deleteRequest)
try self?.context.save()
} catch {
// error
}
}
}
Hope this can help
Solution 8 - Ios
In Swift 3.0
func deleteAllRecords() {
//delete all data
let context = appDelegate.persistentContainer.viewContext
let deleteFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "YourClassName")
let deleteRequest = NSBatchDeleteRequest(fetchRequest: deleteFetch)
do {
try context.execute(deleteRequest)
try context.save()
} catch {
print ("There was an error")
}
}
Solution 9 - Ios
For Swift 4.0 (modified version of svmrajesh's answerā¦ or at least what Xcode turned it into before it would run it for me.)
func deleteAllData(entity: String) {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
fetchRequest.returnsObjectsAsFaults = false
do
{
let results = try managedContext.fetch(fetchRequest)
for managedObject in results
{
let managedObjectData:NSManagedObject = managedObject as! NSManagedObject
managedContext.delete(managedObjectData)
}
} catch let error as NSError {
print("Delete all data in \(entity) error : \(error) \(error.userInfo)")
}
}
Implementation:
deleteAllData(entity: "entityName")
Solution 10 - Ios
In Swift UI
when you select core data at the beginning of project the persistence coordinator is automatically created by swift in app delegate. The scene delegate creates @environmentObject for managed context
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let contentView = ContentView().environment(\.managedObjectContext, context)
create instance of manageObjectContext in content view and also fetchRequest object using property wrapper @FetchRequest
@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: EntityName.entity(), sortDescriptors: []) var entityNames: FetchedResults<EntityName>
For delete action perform
for entityName in entityNames {
moc.delete(entityName)
}
try? moc.save()
try operation can throw error so please implement do try catch block in production code to handle error properly.
Solution 11 - Ios
This clean() method will fetch entities list from DataModel and clear all data.
func deleteAll(entityName: String) -> Error? {
if #available(iOS 9.0, *) {
do {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
try context.execute(batchDeleteRequest)
} catch {
return error
}
return nil
} else {
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
fetchRequest.returnsObjectsAsFaults = false
do
{
let results = try context.fetch(fetchRequest)
for managedObject in results
{
if let managedObjectData:NSManagedObject = managedObject as? NSManagedObject {
context.delete(managedObjectData)
}
}
} catch {
return error
}
return nil
}
}
var objectModel: NSManagedObjectModel? {
if #available(iOS 10.0, *) {
return persistentContainer.managedObjectModel
} else {
return persistentStoreCoordinator?.managedObjectModel
}
}
open func clean() {
if let models = objectModel?.entities {
for entity in models {
if let entityName = entity.name {
_ = deleteAll(entityName: entityName)
}
}
}
}
Happy Coding!
Solution 12 - Ios
Swift 5.1
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try coreDataManager.managedObjectContext.execute(batchDeleteRequest)
} catch {
print("Detele all data in \(entityName) error :", error)
}
Solution 13 - Ios
There are two simple methods as far as i know , first
Method 1:
Fetch, Delete, Repeat
// Initialize Fetch Request
let fetchRequest = NSFetchRequest(entityName: "Item")
// Configure Fetch Request
fetchRequest.includesPropertyValues = false
do {
let items = try managedObjectContext.executeFetchRequest(fetchRequest) as! [NSManagedObject]
for item in items {
managedObjectContext.deleteObject(item)
}
// Save Changes
try managedObjectContext.save()
} catch {
// Error Handling
// ...
}
Methode 2:
Batch Delete Request
// Create Fetch Request
let fetchRequest = NSFetchRequest(entityName: "Item")
// Create Batch Delete Request
let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try managedObjectContext.executeRequest(batchDeleteRequest)
} catch {
// Error Handling
}
I have tested both and they both work fine
Solution 14 - Ios
Swift 5
func deleteAllData(entity: String){
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
fetchRequest.returnsObjectsAsFaults = false
do {
let arrUsrObj = try managedContext.fetch(fetchRequest)
for usrObj in arrUsrObj as! [NSManagedObject] {
managedContext.delete(usrObj)
}
try managedContext.save() //don't forget
} catch let error as NSError {
print("delete fail--",error)
}
}
Solution 15 - Ios
To delete all entries in Core Data I have found 2 ways of doing it
1 - With a for
func
func deleteEntries() {
do {
let managedObjectContext = try CoreDataStack.sharedInstance.getContext()
for record in records {
managedObjectContext.delete(record)
}
try managedObjectContext.save()
} catch let error {
print(error.localizedDescription)
}
}
2 - With a NSBatchDeleteRequest
func deleteEntries() {
do {
let managedObjectContext = try CoreDataStack.sharedInstance.getContext()
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Location")
let request: NSBatchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
try managedObjectContext.execute(request)
try managedObjectContext.save()
} catch let error {
print(error.localizedDescription)
}
}
I recommend using number 2 because is a better way of handling resources in your app
Solution 16 - Ios
An alternative can be to completely remove and recreate persistent store (iOS 10+, swift 3).
let urls = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask);
var dbUrl = urls[urls.count-1];
dbUrl = dbUrl.appendingPathComponent("Application Support/nameOfYourCoredataFile.sqlite")
do {
try persistentContainer.persistentStoreCoordinator.destroyPersistentStore(at: dbUrl, ofType: NSSQLiteStoreType, options: nil);
} catch {
print(error);
}
do {
try persistentContainer.persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: dbUrl, options: nil);
} catch {
print(error);
}
Solution 17 - Ios
Similar to above but with AppDelegte call taken out and UIView variable used
var context: NSManagedObjectContext?
//deleting Message
func deleteMessages(entity: String) {
do {
let request = NSFetchRequest(entityName: entity)
print(request)
if let result = try context!.executeFetchRequest(request) as? [your class of NSManagedObject] {
for message in result {
context!.deleteObject(message)
try context!.save()
print(message)
self.tableView.reloadData()
}
}
} catch {
print("miss")
}
}
To use call function
self.deleteMessages("TimeMaster")
Solution 18 - Ios
I use this one for delete all the core data entities in Swift3
func deleteAllCD(){
for entityName in ["EntityName", "AnotherEntityName"]{
let request = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
let delAllReqVar = NSBatchDeleteRequest(fetchRequest: request)
do { try persistentContainer.viewContext.execute(delAllReqVar) }
catch { print(error) }
}
}
Solution 19 - Ios
Swift 3
// Replace 'MyEntityName' with your managed object class.
let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let fetchRequest: NSFetchRequest<MyEntityName> = MyEntityName.fetchRequest()
fetchRequest.returnsObjectsAsFaults = false
moc.perform {
do {
let myEntities = try fetchRequest.execute()
for myEntity in myEntities {
moc.delete(myEntity)
}
try moc.save()
} catch let error {
print("Delete Error: \(error.localizedDescription)")
}
}
Solution 20 - Ios
Try this:
func deleteAllData(entity: String)
{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let ReqVar = NSFetchRequest(entityName: entity)
let DelAllReqVar = NSBatchDeleteRequest(fetchRequest: ReqVar)
do { try ContxtVar.executeRequest(DelAllReqVar) }
catch { print(error) }
}
Solution 21 - Ios
Swift 4 :
destroyPersistentStoreAtURL(_:withType:options:) will delete (or truncate) the target persistent store. This will safely destroy a persistent store.
Add:
do {
try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: persistentStoreURL, options: nil)
} catch {
// Error Handling
}
Destroy / Delete / Truncate:
do {
try persistentStoreCoordinator.destroyPersistentStoreAtURL(persistentStoreURL, withType: NSSQLiteStoreType, options: nil)
} catch {
// Error Handling
}
Note : Parameters in above method should be identical to addPersistentStoreWithType method. You need to re-initiate storeCoordinator to use store again.
Solution 22 - Ios
For Swift 4.0
func deleteAllData(_ entity:String) {
let managedContext = DatabaseController.getContext().persistentStoreCoordinator
let context = DatabaseController.getContext()
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: entity)
let batchDeleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do {
try managedContext?.execute(batchDeleteRequest, with: context)
}
catch {
print(error)
}
}
Solution 23 - Ios
Swift 4
From iOS 9, there is the possibility of erasing persistent storage. For better maintenance ā create NSPersistentStoreCoordinator extension with abstract function.
extension NSPersistentStoreCoordinator {
func destroyPersistentStore(type: String) -> NSPersistentStore? {
guard
let store = persistentStores.first(where: { $0.type == type }),
let storeURL = store.url
else {
return nil
}
try? destroyPersistentStore(at: storeURL, ofType: store.type, options: nil)
return store
}
}
Then destroying SQLite persistent storage looks pretty simple:
let coordinator = persistentContainer.persistentStoreCoordinator
let store = coordinator.destroyPersistentStore(type: NSSQLiteStoreType)
Recommendations
- Update destroyPersistentStore function which is no-nullable and throws specific errors, for example CoreDataError enum.
- Probably you want to refresh your persistent storage. For this, you can use addPersistentStore function of NSPersistentStoreCoordinator, with retrieved NSPersistentStore object from destroyPersistentStore.
Solution 24 - Ios
static func fetch<T>(entity: T.Type, withPredicate predicate: NSPredicate? = nil) -> Array<T>? where T : NSManagedObject {
let request: NSFetchRequest<T> = NSFetchRequest<T>(entityName: String(describing: T.self))
request.predicate = predicate
do {
return try context.fetch(request)
}catch{
print(error.localizedDescription)
}
return nil
}
static func delete<T>(_ object: T) where T : NSManagedObject {
context.delete(object)
saveContext()
}
static func reset<T>(entity: T.Type) where T : NSManagedObject {
fetch(entity: entity.self)?.forEach{
delete($0)
}
}