Delete ALL Core Data Swift
Asked Answered
N

25

76

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.

Nonagon answered 9/7, 2014 at 16:6 Comment(3)
Well show us some of the various methods you've tried in Swift and maybe we can help you. In terms of APIs and How to do this, that question answers it all and you should just be doing the exact same thing, just in Swift.Middle
Question is already answered here in more efficient way - #1384098Windswept
Does this answer your question? Core Data: Quickest way to delete all instances of an entityScirrhus
N
17

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

Nonagon answered 9/7, 2014 at 17:10 Comment(0)
C
68

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")
Chapell answered 26/11, 2015 at 5:57 Comment(2)
Incorrect Answer: Delete core data doesn't mean that it will contain only single entityUltimate
Use of unresolved identifier 'dataController'; did you mean 'tabBarController'?Acromion
A
44

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)
     }
}
Ashby answered 6/2, 2018 at 11:19 Comment(0)
G
25

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) }
}
Graphology answered 19/7, 2016 at 4:38 Comment(1)
Getting error. Delete rule is not supported for batch deleteFirearm
N
17

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

Nonagon answered 9/7, 2014 at 17:10 Comment(0)
A
13

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)
    }
}
Aplenty answered 2/2, 2017 at 4:42 Comment(0)
B
11

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 one by one. 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

Bauske answered 23/6, 2020 at 10:46 Comment(0)
G
8

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")
    }
}
Grasping answered 18/12, 2017 at 20:16 Comment(1)
You don't need context.save()Firearm
K
6

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")
        }
    }
Kerf answered 19/12, 2017 at 5:11 Comment(0)
K
4

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")
Kelwunn answered 31/3, 2018 at 2:47 Comment(0)
G
4

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.

Grays answered 31/3, 2020 at 19:57 Comment(0)
S
3

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!

Scrape answered 18/1, 2017 at 21:49 Comment(0)
H
3

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)
        }
Hera answered 2/11, 2019 at 7:39 Comment(0)
N
2

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

Nonsense answered 16/12, 2017 at 11:11 Comment(0)
E
2

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)
  }

}
Epp answered 2/1, 2020 at 12:42 Comment(0)
B
2

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

Budgie answered 4/2, 2021 at 13:26 Comment(0)
S
1

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);
    }
Shabbygenteel answered 22/5, 2017 at 9:37 Comment(0)
E
0

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")
Eyas answered 29/2, 2016 at 19:4 Comment(0)
B
0

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) }
    }
}
Berry answered 16/1, 2017 at 13:38 Comment(1)
Delete rule is not supported for batch deleteFirearm
A
0

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)")
    }
}
Assimilative answered 16/1, 2017 at 18:14 Comment(0)
I
0

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) }
}
Idioglossia answered 22/4, 2017 at 5:5 Comment(0)
Z
0

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.

Zwick answered 23/7, 2018 at 11:36 Comment(1)
Doesn't seem to actually delete the database file itself, I needed to also call FileManager.default.removeItem(at: ).Pellikka
T
0

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)
    }


  }
Tailor answered 27/9, 2018 at 11:28 Comment(0)
F
0

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

  1. Update destroyPersistentStore function which is no-nullable and throws specific errors, for example CoreDataError enum.
  2. Probably you want to refresh your persistent storage. For this, you can use addPersistentStore function of NSPersistentStoreCoordinator, with retrieved NSPersistentStore object from destroyPersistentStore.
Fiedler answered 17/10, 2018 at 15:42 Comment(0)
N
0

Here is the solution for Swift 5 & SwiftUI:

let fetchRequest = DataModel.fetchRequest()
let items = try? viewContext.fetch(fetchRequest)
for item in items ?? [] {
    viewContext.delete(item)
    }
try? viewContext.save()

Here DataModel is your model name. You have to pass viewContext:

@Environment(\.managedObjectContext) private var viewContext
Naldo answered 1/2 at 20:4 Comment(0)
F
-1

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {

        guard editingStyle == UITableViewCell.EditingStyle.delete else { return }
        people.remove(at: indexPath.row)

        tableView.deleteRows(at: [indexPath], with: .automatic)
        self.tableView.reloadData()
    }
Fortran answered 6/10, 2022 at 10:54 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Sedda

© 2022 - 2024 — McMap. All rights reserved.