I've been following the CS193p's lectures on Core data and I've run into a problem when I'm inserting a new managed object.
The error is:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+entityForName: could not
locate an entity named 'Card' in this model.'
I've created the "Card" entity in my data model file. However I have a feeling it isn't finding the data model file correctly, since removing that file all together give the same error. I'm wondering how I can find out whether it is due the UIManagedDocument object not finding the data model that is causing this error.
Here is what I'm doing in my controller class:
NSURL *docURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *databaseURL = [docURL URLByAppendingPathComponent:#"Cards Database"];
self.cardsDatabase = [[UIManagedDocument alloc] initWithFileURL:databaseURL];
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.cardsDatabase.fileURL path]]) {
[self.cardsDatabase saveToURL:self.cardsDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
NSLog(#"Done");
}];
} else if (self.cardsDatabase.documentState == UIDocumentStateClosed) {
NSLog(#"Closed");
[self.cardsDatabase openWithCompletionHandler:^(BOOL success) {
if (success) {
NSLog(#"Opened");
[self addSampleData];
}
}];
} else if (self.cardsDatabase.documentState == UIDocumentStateNormal) {
NSLog(#"Normal");
}
- (void)addSampleData
{
NSManagedObjectContext *context = self.cardsDatabase.managedObjectContext;
[context performBlockAndWait:^{
Card *card = [NSEntityDescription insertNewObjectForEntityForName:#"Card" inManagedObjectContext:context];
card.title = #"Test Title";
}];
[self.cardsDatabase saveToURL:self.cardsDatabase.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) {
NSLog(#"Saved");
}];
}
The error occurs on this line:
Card *card = [NSEntityDescription insertNewObjectForEntityForName:#"Card" inManagedObjectContext:context];
Try resetting the simulator(In device, remove the app), clean the build and run again. That should resolve most of the issues related to 'could not locate entities'.
This kind of issue may happen, when you updated your Core Data model, by changing names of attributes of entities, and then Run it without clean(delete) the app with the older Core Data model from the device. Unless you are planning to use light migration or model mapping, please be aware it may happen whenever you Run the app
Related
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.
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
My iCloud Core Data app was running great on iOS7 and ready to launch. When I test on iOS 8 I get the following error and can't seem to fix it when trying to upload data to iCloud.
I suspect my problem is related to how I am getting the document directory and changes in the doc directory with iOS8 but I just can't figure this out..
014-10-12 15:14:17.862 XXXXXXX [4662:236693] __45-[PFUbiquityFilePresenter processPendingURLs]_block_invoke(439): CoreData: Ubiquity: Librarian returned a serious error for starting downloads Error Domain=BRCloudDocsErrorDomain Code=6 "The operation couldn’t be completed. (BRCloudDocsErrorDomain error 6 - Path is outside of any CloudDocs container, will never sync)" UserInfo=0x7f8b1a525f60 {NSDescription=Path is outside of any CloudDocs container, will never sync, NSFilePath=/Users/garyrea/Library/Developer/CoreSimulator/Devices/9AADFE8E-5ECC-4969-9418-57DA45B747C9/data/Containers/Data/Application/AD2E5E62-7295-4371-A08D-1790E8FCCD96/Documents/CoreDataUbiquitySupport/nobody~simA28745A4-A67F-598C-9260-F9AC36609ECF/iCloud/5B8BFA36-1ACA-4966-B7ED-A7344D36ACF1/container/nobody~simA28745A4-A67F-598C-9260-F9AC36609ECF/iCloud/2trlqdMQVpJ~wlEfiLvjWtQfrUJ8YiNCd84KW_xiw4A=/F0CF5F29-D437-4728-B0A2-C5BB90BBC239.1.cdt} with userInfo {
NSDescription = "Path is outside of any CloudDocs container, will never sync";
NSFilePath = "/Users/garyrea/Library/Developer/CoreSimulator/Devices/9AADFE8E-5ECC-4969-9418-57DA45B747C9/data/Containers/Data/Application/AD2E5E62-7295-4371-A08D-1790E8FCCD96/Documents/CoreDataUbiquitySupport/nobody~simA28745A4-A67F-598C-9260-F9AC36609ECF/iCloud/5B8BFA36-1ACA-4966-B7ED-A7344D36ACF1/container/nobody~simA28745A4-A67F-598C-9260-F9AC36609ECF/iCloud/2trlqdMQVpJ~wlEfiLvjWtQfrUJ8YiNCd84KW_xiw4A=/F0CF5F29-D437-4728-B0A2-C5BB90BBC239.1.cdt";
} for these urls: (
"file:///Users/garyrea/Library/Developer/CoreSimulator/Devices/9AADFE8E-5ECC-4969-9418-57DA45B747C9/data/Containers/Data/Application/AD2E5E62-7295-4371-A08D-1790E8FCCD96/Documents/CoreDataUbiquitySupport/nobody~simA28745A4-A67F-598C-9260-F9AC36609ECF/iCloud/5B8BFA36-1ACA-4966-B7ED-A7344D36ACF1/container/nobody~simA28745A4-A67F-598C-9260-F9AC36609ECF/iCloud/2trlqdMQVpJ~wlEfiLvjWtQfrUJ8YiNCd84KW_xiw4A=/F0CF5F29-D437-4728-B0A2-C5BB90BBC239.1.cdt"
)
my app delegate extension code where I create my persistent store is as follows. I have a seed database for first time installation.
- (NSPersistentStoreCoordinator *)createPersistentStoreCoordinator{
NSPersistentStoreCoordinator *persistentStoreCoordinator = nil;
NSManagedObjectModel *managedObjectModel = [self createManagedObjectModel];
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]initWithManagedObjectModel:managedObjectModel];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#
"CoreData.sqlite"];
if (![[NSFileManager defaultManager]fileExistsAtPath:[storeURL path]]){
NSURL *preloadURL=[NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:#"SeedDatabase" ofType:#
"sqlite"]];
NSError *error=nil;
if (![[NSFileManager defaultManager] copyItemAtURL:preloadURL toURL:storeURL error:&error]){
NSLog(#
"File couldnt save");
}
}
NSUbiquitousKeyValueStore *kvStore=[NSUbiquitousKeyValueStore defaultStore];
if (![kvStore boolForKey:#"SEEDED_DATA"]){
NSLog (#
"In the new database");
NSURL *seedStoreURL=[NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:#"SeedDatabase" ofType:#
"sqlite"]];
NSError *seedStoreErrpr;
NSDictionary *seedStoreOptions=#{NSReadOnlyPersistentStoreOption: #YES};
NSPersistentStore *seedStore=[persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:seedStoreURL options:seedStoreOptions error:&seedStoreErrpr];
NSDictionary *iCloudOptions =#{NSPersistentStoreUbiquitousContentNameKey: #"iCloud",
NSMigratePersistentStoresAutomaticallyOption:#YES,
NSInferMappingModelAutomaticallyOption:#YES
};
NSOperationQueue *queue=[[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
NSError *error;
[persistentStoreCoordinator migratePersistentStore:seedStore toURL:storeURL options:iCloudOptions withType:NSSQLiteStoreType error:&error];
NSLog(#
"Persistant store migrated");
[kvStore setBool:YES forKey:#
"SEEDED_DATA"];
// [self checkForDuplicates];
}];
}else{
NSError *error;
NSDictionary *storeOptions =#{NSPersistentStoreUbiquitousContentNameKey: #
"iCloud"
};
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:storeOptions
error:&error]) {
NSLog(#
"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
return persistentStoreCoordinator;
}
- (NSURL *)applicationDocumentsDirectory{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
I was able to resolve this error by specifying the iCloud drive directory (Same name as the one on the developer.apple.com interface).
-(NSURL *)cloudDirectory
{
NSFileManager *fileManager=[NSFileManager defaultManager];
NSString *teamID=#"iCloud";
NSString *bundleID=[[NSBundle mainBundle]bundleIdentifier];
NSString *cloudRoot=[NSString stringWithFormat:#"%#.%#",teamID,bundleID];
NSURL *cloudRootURL=[fileManager URLForUbiquityContainerIdentifier:cloudRoot];
NSLog (#"cloudRootURL=%#",cloudRootURL);
return cloudRootURL;
}
and including it in the icloudOptions Dictionary as a NSPersistentStoreUbiquitousContentURLKey
NSDictionary *storeOptions =#{NSPersistentStoreUbiquitousContentNameKey: #"iCloud",
NSPersistentStoreUbiquitousContentURLKey:[self cloudDirectory],
};
I was getting some strange errors so I removed the app from all devices, deleted the iCloud drive file and re ran on an actual device and it worked fine. Not sure if it runs on IOS7 now but since I only specified the NSPersistentStoreUbiquitousContentURLKey I am pretty confident it should be fine.
I had the same issue during loading some test data.
For the load of the data I was deleting all records.
To avoid the exception a simple sleep(1) between cleaning and loading was enough.
I am trying to use CoreData in a SenTestCase. The problem is the NSManagedObjectModel which is not found. I have tried to initialize it with a URL by searching for the mom file in the application bundle but I could not find it. That is why I switched to:
NSManagedObjectModel *objectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
This does work properly but only in the main application. If I try to run it in the SenTestCase the returned objectModel does not have any entities:
(gdb) po objectModel
(<NSManagedObjectModel: 0xab72480>) isEditable 0, entities {
}, fetch request templates {
}
I have to admit that I do not know what kind of setup is needed to generate the mom file. I have added the .xcdatamodeld file to the list of compiled sources in the application's target and the test target.
The following code is working properly in the applications ViewController viewDidLoad method but is not working in a test case of a SenTestCase class:
- (void)testCoreData {
NSManagedObjectModel *objectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: objectModel];
[context setPersistentStoreCoordinator: coordinator];
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"TestDatabase"];
NSLog(#"Path: %#", url);
NSError *error;
NSPersistentStore *newStore = [coordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:url
options:nil
error:&error];
if (newStore == nil) {
NSLog(#"Store Configuration Failure\n%#",
([error localizedDescription] != nil) ?
[error localizedDescription] : #"Unknown Error");
}
TaskSet *taskSet = [NSEntityDescription insertNewObjectForEntityForName:#"TaskSet"
inManagedObjectContext:context];
taskSet.taskSetId = #"1234";
NSLog(#"TaskSet: %#", taskSet);
NSError *saveError;
if ([context save:&saveError]) {
NSLog(#"Store Saved successfully");
} else {
NSLog(#"Store not saved! Error: %#", saveError);
}
}
Error:
Catchpoint 3 (exception thrown).Unknown.m:0: error: -[ControllerTest testCoreData] : +entityForName: could not locate an entity named 'TaskSet' in this model.
What is the difference between running in a SenTestCase and running in viewDidLoad ? What do I need to do to compile the core data model into a test case?
This question has been answered before: Unit Test can't find Core Data model file
The credit goes to Luther Baker for pointing out that SenTestCases are not using the main Bundle. If you want to write data to a file you have to create the bundle with an identifier as described in his answer.
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.