I\'m using Core Data
in an iOS 7+ app that does not need to save user\'s data, all data the app needs is requested to services and it can be recovered at any time.
Case 1: You're using a SQLite store
This applies if your store type is NSSQLiteStoreType
. Even if you plan to delete your data from time to time, it's not a bad idea to stick to SQLite, as it gives you the flexibility to keep your cached data on disk as long as you wish, and only delete it when you change your model and you don't want to apply any migrations.
Quick solution? Delete your NSPersistentStoreCoordinator
's store at startup, when you're initializing Core Data.
For instance, if you're using the default SQLite store, provided by Apple's boilerplate code:
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"cd.sqlite"]
you can simply delete the file:
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
then use storeURL
to add a new persistent store as usual.
Your NSPersistentStoreCoordinator
won't complain if you have a new model and you won't need any migrations, but your data will be lost, of course.
It goes without saying that you can decide to use this solution when you detect a change in the data model, leaving the store alone if there's no change, so that you can preserve your cached data as long as necessary.
UPDATE:
As suggested by TomHerrington in the comments, to be sure you've removed the old store completely, you should also delete journal files, which might come back and haunt you in the future, if you don't take care of them.
If your store file is named cd.sqlite
, like in the example, the additional files to be removed are cd.sqlite-shm
and cd.sqlite-wal
.
WAL journaling mode for Core Data was introduced as the default in iOS 7 and OSX Mavericks, as reported by Apple in QA1809.
Case 2: Use an in-memory store
As suggested, you could switch to an in-memory store, using NSInMemoryStoreType
instead of NSSQLiteStoreType
. Erasing the store is much easier in this case: all your data resides in memory, all of it will disappear when your app stops running, nothing will remain on disk for you to clean. Next time, you could potentially load a completely different model, without any migrations, as there's no data to migrate.
However, this solution, implemented as it is, wouldn't let you cache data between sessions, which looks like something you'd like to do between app updates (i.e., the store must be erased only when the app is updated and the model changes, while it could be useful to keep it on disk otherwise).
Note:
Both approaches are viable, with their pros and cons, and I'm sure there could be other strategies as well. In the end, you should have all the elements to decide what the best approach would be in your specific case.
Working Swift solution if you target iOS 9 or higher
The shared CoreData manager:
class CoreDataContext {
static let datamodelName = "CoreDataTests"
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
guard let error = error else {
return
}
fatalError(error.localizedDescription)
})
}
static func deleteAndRebuild() {
try! persistentContainer.persistentStoreCoordinator.destroyPersistentStore(at: url, ofType: storeType, options: nil)
loadStores()
}
}
call loadStores
only once in the appDelegate and deleteAndRebuild
when you want to delete and rebuild the database :)
I think destroyPersistentStoreAtURL
method of NSPersistentStoreCoordinator
is what you want.
It will remove the data store and journal files and all other things that need to be removed.
Look at Apple documentation.