How to remove a core data persistent store - objective-c

I need to delete my persistent store (doing it object by object is not practical because I have over 100,000 objects). I've tried this:
- (IBAction)resetDatabase:(id)sender {
NSPersistentStore* store = [[__persistentStoreCoordinator persistentStores] lastObject];
NSError *error = nil;
NSURL *storeURL = store.URL;
// release context and model
[__managedObjectContext release];
[__managedObjectModel release];
__managedObjectModel = nil;
__managedObjectContext = nil;
[__persistentStoreCoordinator removePersistentStore:store error:nil];
[__persistentStoreCoordinator release];
__persistentStoreCoordinator = nil;
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
if (error) {
NSLog(#"filemanager error %#", error);
}
// recreate the stack
__managedObjectContext = [self managedObjectContext];
}
But I get this error when I try to insert entities into the store afterwards:
This NSPersistentStoreCoordinator has no persistent stores. It cannot perform a save operation.
Update:
I tried releasing the MOC and MOM before removing the persistent store but I still get the same error.

Here is how I do a "reset data" function in several apps:
- (void)reset {
// Release CoreData chain
[_managedObjectContext release];
_managedObjectContext = nil;
[_managedObjectModel release];
_managedObjectModel = nil;
[_persistentStoreCoordinator release];
_persistentStoreCoordinator = nil;
// Delete the sqlite file
NSError *error = nil;
if ([fileManager fileExistsAtPath:_storeURL.path])
[fileManager removeItemAtURL:_storeURL error:&error];
// handle error...
}
Basically I just release the CoreData chain, then delete the persistentStore file. That's what you are trying to do, without using removePersistentStore, which I do not care since I will just rebuild the persistentStore coordinator later. Then at next core data call the chain is rebuilt transparently using singleton-lazy-style constructors like :
- (NSManagedObjectModel *) managedObjectModel {
if (!_managedObjectModel)
_managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
return _managedObjectModel;
}

You can do it externally given that you only need to do this while developing your application. I have a terminal open in which I remove the store manually before re-running my app. All you need to know is where it is located. I log it to console everytime my app runs with the following code:
[[CoreDataSingleton sharedManager] managedObjectContext]; //be sure to create the store first!
//Find targeted mom file in the Resources directory
NSString *momPath = [[NSBundle mainBundle] pathForResource:#"Parking" ofType:#"mom"];
NSLog(#"momd path: %#",momPath);
Hope that helps!

You need to make sure that any managed object context attached to the persistent store have been released before you try to delete the store. Otherwise, the context will evoke that error.

Related

CoreData NSManagedObjectContext not found

New to iOS development. I am trying to use the core data stack in a sample app, which fetches data over network and simply updates the UI. Whilst creating the project, the "Use Core Data" checkbox was ticked which generates bunch of boilerplate code. However, on XCode 8.2.1, the I only see the NSPersistentContainer implementation within the AppDelegate.m file.
- (NSPersistentContainer *)persistentContainer {
// The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
#synchronized (self) {
if (_persistentContainer == nil) {
_persistentContainer = [[NSPersistentContainer alloc] initWithName:#"ergast_coredata_objc"];
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
NSLog(#"Unresolved error %#, %#", error, error.userInfo);
abort();
}
}];
}
}
return _persistentContainer;
}
There is no boilerplate code for the NSManagedObjectContext as most of the tutorials would have you believe.
Hence, the following block within the ViewController.m class fails with a Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AppDelegate managedObjectContext]: unrecognized selector sent to instance
-(NSArray *)getSeasonsList{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"SeasonData"];
NSError *error = nil;
NSArray *results = [[self getManagedObjectContext] executeFetchRequest:request error:&error];
if (!results) {
NSLog(#"Error fetching objects: %#\n%#", [error localizedDescription], [error userInfo]);
abort();
}
return results;
}
- (NSManagedObjectContext *)getManagedObjectContext {
NSManagedObjectContext *context = nil;
id delegate = [[UIApplication sharedApplication] delegate];
context = [delegate managedObjectContext];
return context;
}
Tried looking online but most of the tutorials are Swift based it seems. What am i missing here? Is the developer supposed to provide the implementation for the NSManagedObjectContext? Would be much appreciated if someone can provide with an Objective-c based sample code.
Thanks!
See in saveContext method
pragma mark - Core Data Saving support
- (void)saveContext {
// OBSERVE HERE
NSManagedObjectContext *context = self.persistentContainer.viewContext;
NSError *error = nil;
if ([context hasChanges] && ![context save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, error.userInfo);
abort();
}
}
Whenever you need NSManagedObjectContext instance, access like this
NSManagedObjectContext *context = self.persistentContainer.viewContext;
self.persistentContainer OR classObject.persistentContainer
Modify the "getManagedObjectContext" method as below
- (NSManagedObjectContext *)getManagedObjectContext {
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [[delegate persistentContainer] viewContext];
return context;
}
I didn't tested this, but hope this will work
I have a category for appdelegate that was included in one of the old Stanford CS193P that uses objective-c. Some of it might be deprecated, though. Also check out https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/InitializingtheCoreDataStack.html#//apple_ref/doc/uid/TP40001075-CH4-SW1 has objective-c sample. Post back if that helps.
//
// PhotomaniaAppDelegate+MOC.m
// Photomania
//
// This code comes from the Xcode template for Master-Detail application.
#import "PhotomaniaAppDelegate+MOC.h"
#import <CoreData/CoreData.h>
#implementation PhotomaniaAppDelegate (MOC)
#pragma mark - Core Data
- (void)saveContext:(NSManagedObjectContext *)managedObjectContext
{
NSError *error = nil;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)createMainQueueManagedObjectContext
{
NSManagedObjectContext *managedObjectContext = nil;
NSPersistentStoreCoordinator *coordinator = [self createPersistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return managedObjectContext;
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)createManagedObjectModel
{
NSManagedObjectModel *managedObjectModel = nil;
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"Photomania" withExtension:#"momd"];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return managedObjectModel;
}
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)createPersistentStoreCoordinator
{
NSPersistentStoreCoordinator *persistentStoreCoordinator = nil;
NSManagedObjectModel *managedObjectModel = [self createManagedObjectModel];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"MOC.sqlite"];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
Typical reasons for an error here include:
* The persistent store is not accessible;
* The schema for the persistent store is incompatible with current managed object model.
Check the error message to determine what the actual problem was.
If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
If you encounter schema incompatibility errors during development, you can reduce their frequency by:
* Simply deleting the existing store:
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]
* Performing automatic lightweight migration by passing the following dictionary as the options parameter:
#{NSMigratePersistentStoresAutomaticallyOption:#YES, NSInferMappingModelAutomaticallyOption:#YES}
Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator;
}
// Returns the URL to the application's Documents directory
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
#end
Also, check out this project https://github.com/m2mtech/photomania-2013-14/tree/master/Photomania/CoreDataTableViewController/MOC More info how Core Data was used with this implementation.

How to re-use Core Data in Extension code in Objective-C? The managedObjectContext can't be created by UIApplicationDelegate as we use to do

The problem I meet is we can't get the managedObjectContext by this way:
[((MDAppDelegate*)appController) mainQueueContext] ;
Because the error message is:
'sharedApplication' is unavailable: not available on iOS (App
Extension) - Use view controller based solutions where appropriate
instead.
My QUESTION is:
Is there any existing example to help us connect to Core Data through Extension (Today/Watch)?
P.S. I have read following questions, none of them help. I just need an example:
App and Extension - Use Core data == error : sharedApplication()' is unavailable
WatchKit : 'sharedApplication' is unavailable: not available on iOS (App Extension) - Use view controller based solutions where appropriate instead
Use AppDelegate in today extension
We found and fix the problem now. The problem is caused by my misunderstanding of Core Data. We used to re-use tutorial's source code. When the system is work, we have no time to get deep understand of it.
The problem is we can't use Container App's managed object context. To fix it we use following code:
replace
[((MDAppDelegate*)appController) mainQueueContext] ;
to
[self mainQueueContext] ;
Then, add following...
- (NSManagedObjectContext *)mainQueueContext {
if (_mainQueueContext != nil) {
return _mainQueueContext;
}
_mainQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainQueueContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
[_mainQueueContext setPersistentStoreCoordinator:self.persistentStoreCoordinator];
return _mainQueueContext; }
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL;
NSString *containerPath = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:#"group.<your project group ID>"].path;
NSString *sqlitePath = [NSString stringWithFormat:#"file://%#/%#", containerPath, #"<Your database file>.sqlite"];
storeURL = [NSURL URLWithString:sqlitePath];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = #{
NSMigratePersistentStoresAutomaticallyOption : #YES,
NSInferMappingModelAutomaticallyOption : #YES
};
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&error]) {
abort();
}
NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
if (![[NSFileManager defaultManager] setAttributes:fileAttributes ofItemAtPath:storeURL.path error:&error]) {
// Handle error
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL;
NSString *containerPath = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:#"group.<your project group ID>"].path;
NSString *modelPath = [NSString stringWithFormat:#"file://%#/%#", containerPath, #"<Your database file>.momd"];
modelURL = [NSURL URLWithString:modelPath];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
Another Important issue is the Container App is still using the Core Data store located in application's Documents directory. The extension can't access it. So, we migrate the store to group shared folder using below lines:
NSString *directoryShared = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:#"group.<your project group ID>"].path;
NSString *storePathShared = [NSString stringWithFormat:#"file://%#/%#", directoryShared, #"<Your database file>.sqlite"];
NSURL *storeUrlShared = [NSURL URLWithString:storePathShared];
[_persistentStoreCoordinator migratePersistentStore:store
toURL:storeUrlShared
options:options
withType:NSSQLiteStoreType
error:&error];
if (error != nil) {
NSLog(#"Error when migration to groupd url %#, %#", error, [error userInfo]);
}
We just leave the original database alone, let the container app keep using it. there are some better way to achieve it. like:
Migrating NSPersistentStore from application sandbox to shared group container

NSFetchedResultsController requires a non-nil fetchRequest and managedObjectContext

i am having a problem since days, i tryed all the solutions here in stackoverflow but anyone gives me a solution.
i am using core data and tableviewcontroller.
My CoreDataTableViewController its correct, i downloaded it from timroadnley and u use it in another projects.
Im getting an error : 'An instance of NSFetchedResultsController requires a non-nil fetchRequest and managedObjectContext'
The application loads correctly but when i press to go to the marksTableviewcontroller, it fails.
THE ERROR IS ON THIS LINE:
- (void)setupFetchedResultsController{
// 1 - Decide what Entity you want
NSString *entityName = #"Marks"; // Put your entity name here
NSLog(#"Setting up a Fetched Results Controller for the Entity named %#", entityName);
// 2 - Request that Entity
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
// 4 - Sort it if you want
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"subject"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)]];
// 5 - Fetch it
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil]; //IN THIS LILE IS THE ERROR, IN "REQUEST"
[self performFetch];
}
THIS IS MY APPDELEGATE:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
marksTVCon.managedObjectContext = self.managedObjectContext;
NSDictionary *defaultsDict = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithBool:YES], #"FirstLaunch", nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultsDict];
NSUserDefaults *sharedDefaults = [NSUserDefaults standardUserDefaults];
if([sharedDefaults boolForKey:#"FirstLaunch"]) {
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"MYAPP" message:#"Thanks for downloading, hope you love our app" delegate:nil cancelButtonTitle:#"Go app" otherButtonTitles:nil, nil];
[message show];
[sharedDefaults setBool:NO forKey:#"FirstLaunch"];
[sharedDefaults synchronize];
}
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Saves changes in the application's managed object context before the application terminates.
[self saveContext];
}
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
}
#pragma mark - Core Data stack
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"MYAPP" withExtension:#"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"MYAPP.sqlite"];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
Typical reasons for an error here include:
* The persistent store is not accessible;
* The schema for the persistent store is incompatible with current managed object model.
Check the error message to determine what the actual problem was.
If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
If you encounter schema incompatibility errors during development, you can reduce their frequency by:
* Simply deleting the existing store:
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]
* Performing automatic lightweight migration by passing the following dictionary as the options parameter:
#{NSMigratePersistentStoresAutomaticallyOption:#YES, NSInferMappingModelAutomaticallyOption:#YES}
Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
*/
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
#end
If you need to ask for anyother peace of code pliz ask for it, I think the problem is in there, but im not pretty Sure.

Clearing CoreData and all that inside

I'm pretty new to CoreData and this app that uses it.
And I'm currently working on a feature that clears the entire core data when I log out in the app.
I have 2 sqllite files (for some reason they thought that was handy)
How can I clear both files of all data and reset them into a dataless state?
I've tried a lot of ways, following guides, on SO.
How to clear/reset all CoreData in one-to-many relationship
how to remove all objects from Core Data
They all seem to fail for me.
Now I'm wondering what do I do wrong? And perhaps someone can explain me how to reset my 2 CoreData files the proper way.
EDIT:
//should clear the whole coredata database. mainly used for logout mechanism
-(void)resetCoreData
{
for (NSPersistentStore *store in self.persistentStoreCoordinator.persistentStores)
{
// NSPersistentStore *store = self.persistentStoreCoordinator.persistentStores[0];
NSError *error;
NSURL *storeURL = store.URL;
DLog(#"storeURL: %#", storeURL);
NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
DLog(#"There are erreurs: %#", error);
// [self addDefaultData];
}
_persistentStoreCoordinator = nil;
_managedObjectContext = nil;
_managedObjectModel = nil;
}
This doesn't seem to clear the CoreData for me.
EDIT2:
- (NSManagedObjectContext *)managedObjectContext
{
    if (_managedObjectContext != nil) {
        return _managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    if (coordinator != nil) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return _managedObjectContext;
}
- (NSManagedObjectModel *)managedObjectModel
{
if (__managedObjectModel != nil) {
return __managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"MyName" withExtension:#"momd"];
__managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return __managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (__persistentStoreCoordinator != nil) {
return __persistentStoreCoordinator;
}
NSString *storePath = [[self applicationDocumentsDirectory]
stringByAppendingPathComponent:#"MyName.sqlite"];
NSFileManager *fileManager = [NSFileManager defaultManager];
// If the expected store doesn't exist, copy the default store.
if (![fileManager fileExistsAtPath:storePath]) {
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:#"MyName" ofType:#"momd"];
if (defaultStorePath) {
[fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL];
}
}
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
//Check to see what version of the current model we're in. If it's >= 2.0,
//then and ONLY then check if migration has been performed...
NSSet *versionIdentifiers = [[self managedObjectModel] versionIdentifiers];
DLog(#"Which Current Version is our .xcdatamodeld file set to? %#", versionIdentifiers);
if ([versionIdentifiers containsObject:#"2.0"])
{
BOOL hasMigrated = YES;
if (hasMigrated==YES) {
storePath = nil;
storePath = [[self applicationDocumentsDirectory]
stringByAppendingPathComponent:#"MyName2.sqlite"];
}
}
NSURL *storeUrl = [NSURL fileURLWithPath:storePath];
NSError *error;
NSDictionary *pscOptions = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:NO], NSInferMappingModelAutomaticallyOption,
nil];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeUrl
options:pscOptions
error:&error]) {
DLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
Edit 3:
I'm still looking for a way to reset my CoreData as if I deleted the entire app and started it up again. The usual ways of doing so are not working for my case. And there are 2 sqllite files. There are hints of a migration that took place at some point in the application but I'm not too sure when and how. Error logs show nothing useful.
I'm not looking for the most efficient way. Just the way.
Help me out and the bounty is yours.
Edit 4:
FINAL RESULT:
It seemed my legacy code had a second ManagedObjectContext instantiated. The moment I retrieved it and did the flush-function with it. Both sqlite-files disappeared as was needed.
Thanks to all that put effort in my problem.
try the following method to flush the database, it works perfect for me.
-(void) flushDatabase{
[__managedObjectContext lock];
NSArray *stores = [__persistentStoreCoordinator persistentStores];
for(NSPersistentStore *store in stores) {
[__persistentStoreCoordinator removePersistentStore:store error:nil];
[[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:nil];
}
[__managedObjectContext unlock];
__managedObjectModel = nil;
__managedObjectContext = nil;
__persistentStoreCoordinator = nil;
}
NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
So you're removing the persistent store from the persistent store coordinator, and then trying to delete the file. But just removing the store from the coordinator isn't enough to guarantee that the file associated with the store has been closed, and if it hasn't then the file system will probably prevent you from deleting the file. I can't tell from your question whether you're using ARC here, but since you say that it's old code there's a good chance that you aren't. Either way, if removing the store causes it to be autoreleased instead of released, or if you keep any other references to the store anywhere, then the store won't be deallocated just because you removed it from the coordinator, the file may remain open, and deleting the file will fail.
A good way to see what's really going on, in addition to looking at the error object provided by -removeItemAtPath:error:, is to take a look in the file system and see whether the file is still there after you try to remove it. Go to the Organizer window, select your device and application, and download a copy of the app's sandbox. You should then be able to see whether the file is really being deleted.
If you do see that the files are being deleted as you think they should be, then look for other ways that the data may be restored. If UserA logs out and then UserB logs into the app while it's still running, are you sure that you've started with a fresh managed object context? Is it possible that UserA's data remains in the MOC? It could then be written out when you create and add a new store. Another possibility that occurs to me is that iCloud is "helping" here. I see that your data files are kept in the Documents directory, and iOS will normally try to keep files in that directory backed up to iCloud. Perhaps when you create a new store for UserB's data, iCloud adds UserA's records back to that store. (Seems unlikely -- I'm pretty sure iCloud is more sophisticated than that -- but something to check.)
I use this function in the AppDelegate of one of my apps...
- (void)deleteAllCoreData
{
NSPersistentStore *store = self.persistentStoreCoordinator.persistentStores[0];
NSError *error;
NSURL *storeURL = store.URL;
NSPersistentStoreCoordinator *storeCoordinator = self.persistentStoreCoordinator;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:storeURL.path error:&error];
__persistentStoreCoordinator = nil;
__managedObjectContext = nil;
__managedObjectModel = nil;
[self addDefaultData];
}
It deletes the persistent store that CoreData uses and leaves it so that a new one is set up when core data is accessed again.
This is the method described in the second link you provided.
If your app can create the files then just remove them when the app quits.
If you have some notion of a database that has valuable schema info, and you just need to truncate the file, that isn't really the case in core data... The schema is in the compiled entity models and xcwhatever files.
Also I must have just read it wrong, because if you want core data to be not persistent then you are using the wrong tool.

insertNewObjectForEntityForName:

I set up an Entity using the Xcode .xcdatamodel file editor. I created an entity called Person, added a few attributes, then generated a .m file to represent it. That all works fine.
Now when I go to write a line of code like:
Person * person = (Person*)[NSEntityDescription
insertNewObjectForEntityForName:#"Person"
inManagedObjectContext:managedObjectContext];
And I get:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+entityForName: could not locate an NSManagedObjectModel for entity name 'Person''
I followed the Location example exactly though, step-for-step I believe, but I think I must have missed some kind of crucial "registration" step where I tell Xcode that my Person entity should be accessible.. Also I didn't have a way to "initialize" the managedObjectContext at all, the Location example doesn't seem to do that either.
The fact that you didn't set up the MOC is almost certainly the problem. Most specifically, it means you're probably not loading your MOM (Managed Object Model) that defines Person. Somewhere in your code you should have something like this:
managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
And something like this:
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
And something like this:
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator: coordinator];
I'm just copying lines out of the AppDelegate of the Core Data template (what you get if you make a new application that uses Core Data).
If you have all that, make sure that your xcdatamodel is listed in your Compile Sources step of the build. And of course make sure that Person is actually the Entity name in your xcdatamodel. Entity name is not the same as Class, though they are often set to be the same.
You need the init of the Core Data
-(void)initCoreData{
NSError *error;
//Path to sqlite file.
NSString *path = [NSHomeDirectory() stringByAppendingString:#"/Documents/Level4.sqlite"];
NSURL *url = [NSURL fileURLWithPath:path];
//init the model
NSManagedObjectModel *managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
//Establish the persistent store coordinator
NSPersistentStoreCoordinator *persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:managedObjectModel];
if(![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error]){
NSLog(#"Error %#",[error localizedDescription]);
}else{
self.context = [[[NSManagedObjectContext alloc ] init ] autorelease];
[self.context setPersistentStoreCoordinator:persistentStoreCoordinator];
}
[persistentStoreCoordinator release];
}
You should check if the NSManagedObjectContext object is nil.
e.g.
if (self.managedObjectContext == nil) {
NSLog(#"NSManagedObjectContext is nil");
return nil;
}