Delete/Reset all entries in Core Data?

后端 未结 30 2715
天命终不由人
天命终不由人 2020-11-22 16:00

Do you know of any way to delete all of the entries stored in Core Data? My schema should stay the same; I just want to reset it to blank.


Edit

相关标签:
30条回答
  • 2020-11-22 16:13

    Swift 4/5, iOS 9+

    Rebuilding the whole CoreData SQLite file will make sure all data is erased, therefore all entities are deleted. Just call deleteAndRebuild().

    class CoreDataStack {
        // Change this
        static let datamodelName = "ProjectName"
        static let storeType = "sqlite"
    
        static let persistentContainer = NSPersistentContainer(name: datamodelName)
        private static let url: URL = {
            let url = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)[0].appendingPathComponent("\(datamodelName).\(storeType)")
    
            assert(FileManager.default.fileExists(atPath: url.path))
    
            return url
        }()
    
        static func loadStores() {
            persistentContainer.loadPersistentStores(completionHandler: { (nsPersistentStoreDescription, error) in
                if let error = error {
                    fatalError(error.localizedDescription)
                }
            })
        }
    
        static func deleteAndRebuild() {
            try! persistentContainer.persistentStoreCoordinator.destroyPersistentStore(at: url, ofType: storeType, options: nil)
    
            loadStores()
        }
    }
    
    0 讨论(0)
  • 2020-11-22 16:13

    here my swift3 version for delete all records. 'Users' is entity name

    @IBAction func btnDelAll_touchupinside(_ sender: Any) {
    
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        let managedObjectContext = appDelegate.persistentContainer.viewContext
    
        let fetchReq = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
        let req = NSBatchDeleteRequest(fetchRequest: fetchReq)
    
        do {
            try managedObjectContext.execute(req)
    
        } catch {
            // Error Handling
        }   
    }
    
    0 讨论(0)
  • 2020-11-22 16:15

    I've written a clearStores method that goes through every store and delete it both from the coordinator and the filesystem (error handling left aside):

    NSArray *stores = [persistentStoreCoordinator persistentStores];
    
    for(NSPersistentStore *store in stores) {
        [persistentStoreCoordinator removePersistentStore:store error:nil];
        [[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:nil];
    }
    
    [persistentStoreCoordinator release], persistentStoreCoordinator = nil;
    

    This method is inside a coreDataHelper class that takes care of (among other things) creating the persistentStore when it's nil.

    0 讨论(0)
  • 2020-11-22 16:15

    Delete the persistent store file and setup a new persistent store coordinator?

    0 讨论(0)
  • 2020-11-22 16:15

    Assuming you are using MagicalRecord and have a default persistence store:

    I don't like all the solutions that assume certain files to exist and/or demand entering the entities names or classes. This is a Swift(2), safe way to delete all the data from all the entities. After deleting it will recreate a fresh stack too (I am actually not sure as to how neccessery this part is).

    It's godo for "logout" style situations when you want to delete everything but have a working store and moc to get new data in (once the user logs in...)

    extension NSManagedObject {
    
        class func dropAllData() {
    
            MagicalRecord.saveWithBlock({ context in
    
                for name in NSManagedObjectModel.MR_defaultManagedObjectModel().entitiesByName.keys {
                    do { try self.deleteAll(name, context: context) }
                    catch { print("⚠️ ✏️ Error when deleting \(name): \(error)") }
                }
    
                }) { done, err in
                    MagicalRecord.cleanUp()
                    MagicalRecord.setupCoreDataStackWithStoreNamed("myStoreName")
            }
        }
    
        private class func deleteAll(name: String, context ctx: NSManagedObjectContext) throws {
            let all = NSFetchRequest(entityName: name)
            all.includesPropertyValues = false
    
            let allObjs = try ctx.executeFetchRequest(all)
            for obj in allObjs {
                obj.MR_deleteEntityInContext(ctx)
            }
    
        }
    }
    
    0 讨论(0)
  • 2020-11-22 16:17

    [Late answer in response to a bounty asking for newer responses]

    Looking over earlier answers,

    • Fetching and deleting all items, as suggested by @Grouchal and others, is still an effective and useful solution. If you have very large data stores then it might be slow, but it still works very well.
    • Simply removing the data store is, as you and @groundhog note, no longer effective. It's obsolete even if you don't use external binary storage because iOS 7 uses WAL mode for SQLite journalling. With WAL mode there may be (potentially large) journal files sitting around for any Core Data persistent store.

    But there's a different, similar approach to removing the persistent store that does work. The key is to put your persistent store file in its own sub-directory that doesn't contain anything else. Don't just stick it in the documents directory (or wherever), create a new sub-directory just for the persistent store. The contents of that directory will end up being the persistent store file, the journal files, and the external binary files. If you want to nuke the entire data store, delete that directory and they'll all disappear.

    You'd do something like this when setting up your persistent store:

    NSURL *storeDirectoryURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"persistent-store"];
    if ([[NSFileManager defaultManager] createDirectoryAtURL:storeDirectoryURL
            withIntermediateDirectories:NO
            attributes:nil
            error:nil]) {
        NSURL *storeURL = [storeDirectoryURL URLByAppendingPathComponent:@"MyApp.sqlite"];
        // continue with storeURL as usual...
    }
    

    Then when you wanted to remove the store,

    [[NSFileManager defaultManager] removeItemAtURL:storeDirectoryURL error:nil];
    

    That recursively removes both the custom sub-directory and all of the Core Data files in it.

    This only works if you don't already have your persistent store in the same folder as other, important data. Like the documents directory, which probably has other useful stuff in it. If that's your situation, you could get the same effect by looking for files that you do want to keep and removing everything else. Something like:

    NSString *docsDirectoryPath = [[self applicationDocumentsDirectory] path];
    NSArray *docsDirectoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:docsDirectoryPath error:nil];
    for (NSString *docsDirectoryItem in docsDirectoryContents) {
        // Look at docsDirectoryItem. If it's something you want to keep, do nothing.
        // If it's something you don't recognize, remove it.
    }
    

    This approach may be error prone. You've got to be absolutely sure that you know every file you want to keep, because otherwise you might remove important data. On the other hand, you can remove the external binary files without actually knowing the file/directory name used to store them.

    0 讨论(0)
提交回复
热议问题