I have Core Data working in my app. So, I fetch an XML file, parse the data into model objects and insert them into core data. They are saved in the persistent store and I can access them when I relaunch the app. However, I want to be able to refresh the data in the persistent store at will, so I need to first remove existing objects from the store. Is there a straight-forward method for this?
Thanks
I found this solution:
[managedObjectContext lock];
[managedObjectContext reset];//to drop pending changes
if ([persistentStoreCoordinator removePersistentStore:persistentStore error:&error])
{
NSURL* storeURL = [NSUR开发者_运维百科L fileURLWithPath:[self pathForPersistentStore]];
[[NSFileManager defaultManager] removeFileAtPath:[storeURL path] handler:nil];
[self addPersistentStore];//recreates the persistent store
}
[managedObjectContext unlock];
Here's what I have done to clean my Core Data entirely. It works perfectly. This is if you only have one persistent store which is probably the case if you didn't add one more manually. If your managedObjectContext has the same name as here you can simply copy/past it will work.
NSError * error;
// retrieve the store URL
NSURL * storeURL = [[managedObjectContext persistentStoreCoordinator] URLForPersistentStore:[[[managedObjectContext persistentStoreCoordinator] persistentStores] lastObject]];
// lock the current context
[managedObjectContext lock];
[managedObjectContext reset];//to drop pending changes
//delete the store from the current managedObjectContext
if ([[managedObjectContext persistentStoreCoordinator] removePersistentStore:[[[managedObjectContext persistentStoreCoordinator] persistentStores] lastObject] error:&error])
{
// remove the file containing the data
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
//recreate the store like in the appDelegate method
[[managedObjectContext persistentStoreCoordinator] addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error];//recreates the persistent store
}
[managedObjectContext unlock];
//that's it !
swift version of @Nicolas Manzini answer:
if let psc = self.managedObjectContext?.persistentStoreCoordinator{
if let store = psc.persistentStores.last as? NSPersistentStore{
let storeUrl = psc.URLForPersistentStore(store)
self.managedObjectContext?.performBlockAndWait(){
self.managedObjectContext?.reset()
var error:NSError?
if psc.removePersistentStore(store, error: &error){
NSFileManager.defaultManager().removeItemAtURL(storeUrl, error: &error)
psc.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeUrl, options: nil, error: &error)
}
}
}
}
Based on @Nicolas Manzini answer I have wrote a Swift 2.1 version with little improvements. I have added an extension to NSManagedObjectContext
. Full code below:
import Foundation
import CoreData
extension NSManagedObjectContext
{
func deleteAllData()
{
guard let persistentStore = persistentStoreCoordinator?.persistentStores.last else {
return
}
guard let url = persistentStoreCoordinator?.URLForPersistentStore(persistentStore) else {
return
}
performBlockAndWait { () -> Void in
self.reset()
do
{
try self.persistentStoreCoordinator?.removePersistentStore(persistentStore)
try NSFileManager.defaultManager().removeItemAtURL(url)
try self.persistentStoreCoordinator?.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
}
catch { /*dealing with errors up to the usage*/ }
}
}
}
There is a function
According to WWDC 242, you can use it for clearing a database.
Also there is a func replacePersistentStore
which is replacing the current database with a selected one.
You could loop through all objects and delete them by doing this:
[managedObjectContext deleteObject:someObject];
If you want to remove all objects it is probably fastest to delete the store and then recreate the CoreData stack.
Trash your data file and remake it.
import Foundation
import CoreData
extension NSManagedObjectContext
{
func deleteAllData() {
guard let persistentStore = persistentStoreCoordinator?.persistentStores.last else {
return
}
guard let url = persistentStoreCoordinator?.url(for: persistentStore) else {
return
}
performAndWait { () -> Void in
self.reset()
do
{
try self.persistentStoreCoordinator?.remove(persistentStore)
try FileManager.default.removeItem(at: url)
try self.persistentStoreCoordinator?.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
}
catch { /*dealing with errors up to the usage*/ }
}
}
}
Thanks @Julian Krol - updated answer for Swift 5.1
The fastest way to ditch everything is to send your managed object context the reset
message.
精彩评论