how can I remove all objects? I know I can remove one by
[managedObjectContext deleteObject:objToDelete];
is it possible to delete all without iterating all array?
thanks
This function removes the current SQLite db file from disk and creates a new one. It's much faster than any iterative delete.
-(void)deleteAndRecreateStore{
NSPersistentStore * store = [[self.persistentStoreCoordinator persistentStores] lastObject];
NSError * error;
[self.persistentStoreCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtURL:[store URL] error:&error];
__managedObjectContext = nil;
__persistentStoreCoordinator = nil;
[self managedObjectContext];//Rebuild The CoreData Stack
}
If you want to call this outside Application Delegate (assuming boilerplate CoreData integration) you can use this to get a reference to your app delegate:
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplication sharedApplication] delegate];
Don't forget to import the header.
Marking objects for deletion and then saving works the way it does because Core Data still needs to run the validation rules for all of the objects being deleted. After all, an object can refuse deletion based on how it responds to -validateForDelete:.
If:
you truly want to delete everything in a persistent store
and you don't care about whether the objects in that persistent store say they're valid for deletion
Then:
tear down the Core Data stack that's using that persistent store
and delete the persistent store's file.
this is what I do to "reset" my data store:
- (BOOL)resetDatastore
{
[[self managedObjectContext] lock];
[[self managedObjectContext] reset];
NSPersistentStore *store = [[[self persistentStoreCoordinator] persistentStores] lastObject];
BOOL resetOk = NO;
if (store)
{
NSURL *storeUrl = store.URL;
NSError *error;
if ([[self persistentStoreCoordinator] removePersistentStore:store error:&error])
{
[[self persistentStoreCoordinator] release];
__persistentStoreCoordinator = nil;
[[self managedObjectContext] release];
__managedObjectContext = nil;
if (![[NSFileManager defaultManager] removeItemAtPath:storeUrl.path error:&error])
{
NSLog(#"\nresetDatastore. Error removing file of persistent store: %#",
[error localizedDescription]);
resetOk = NO;
}
else
{
//now recreate persistent store
[self persistentStoreCoordinator];
[[self managedObjectContext] unlock];
resetOk = YES;
}
}
else
{
NSLog(#"\nresetDatastore. Error removing persistent store: %#",
[error localizedDescription]);
resetOk = NO;
}
return resetOk;
}
else
{
NSLog(#"\nresetDatastore. Could not find the persistent store");
return resetOk;
}
}
You can also just tear down the stack (releasing the NSManagedObjectContext, NSPersistentStore and NSManagedObjectModel) and delete the file. Probably would be faster than iterating over your entire database and deleting each object individually.
Also, it is unlikely they will provide this functionality in the future because it is easy to delete the file. However if you feel it is important then file a radar and let Apple know. Otherwise they won't know how many people want this feature.
Just iterate the array and delete them. There isn't a defined method for deleting them all.
When you remove all the cache and documents, you are deleting the database. Not is necesary call to managedObjectContext
NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSArray *caches = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSMutableArray *paths = [NSMutableArray array];
[paths addObjectsFromArray:documents];
[paths addObjectsFromArray:caches];
for (NSUInteger i = 0; i < [paths count]; i++) {
NSString *folderPath = [paths objectAtIndex:i];
NSLog(#"Attempting to remove contents for: %#", folderPath);
//Remove all cached data in the local app directory
NSArray *dirContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:folderPath error:&error];
for (NSString *strName in dirContents) {
[[NSFileManager defaultManager] removeItemAtPath:[folderPath stringByAppendingPathComponent:strName] error:&error];
if (error != nil) {
NSLog(#"Error removing item: %# : %#", strName, error.description);
} else {
NSLog(#"Removed item: %#", strName);
}
}
}
I used stifin's code and updated it to use -performBlockAndWait:
- (BOOL)reset
{
__block BOOL result = YES;
[[self mainContext] performBlockAndWait:^{
[[self mainContext] reset];
NSArray* stores = [[self persistentStoreCoordinator] persistentStores];
_mainContext = nil;
_persistedContext = nil;
for(NSPersistentStore* store in stores) {
NSError* error;
if(![[self persistentStoreCoordinator] removePersistentStore:store error:&error]) {
debuglog(#"Error removing persistent store: %#", [error localizedDescription]);
result = NO;
}
else {
if(![[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:&error]) {
debuglog(#"Error removing file of persistent store: %#", [error localizedDescription]);
result = NO;
}
}
}
_persistentStoreCoordinator = nil;
}];
return result;
}
Related
Step 1: I open a document
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentDirectory = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
NSString *documentName = #"MyDocument";
NSURL *url = [documentDirectory URLByAppendingPathComponent:documentName];
document = [[UIManagedDocument alloc] initWithFileURL:url];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:url.path];
if (fileExists) {
[document openWithCompletionHandler:^(BOOL success) {[self documentOpened:success];}];
}else{
[document saveToURL:url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){[self documentOpened:success];}];
}
...
-(void)documentOpened:(BOOL)success
{
NSLog(#"Document opened");
if (success)
{
if (self.document.documentState == UIDocumentStateNormal)
{
self.managedObjectContext = document.managedObjectContext;
[self.managedObjectContext setUndoManager:nil];
// [self loadGames];
}
}else
{
NSLog(#"Fail to open file");
}
}
step 2: I fetch an object
+(Game*) gameWithDate:(NSDate*)date
inContext:(NSManagedObjectContext*)context
{
Game* res;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Game"];
request.predicate = [NSPredicate predicateWithFormat:#"date == %#", date];
NSError *error;
NSArray *matches = [context executeFetchRequest:request error:&error ];
if(!matches || error || [matches count] > 1)
{
NSLog(#"Error: NO Game in DB");
}else
{
if ([matches count])
{
res = [matches firstObject];
NSLog(#"Fetching existing game");
}else
{
NSLog(#"Creating a game");
}
}
return res;
}
step 3: I delete the object:
Game *g = [Game gameWithDate:lastDate inContext:managedObjectContext];
[managedObjectContext deleteObject:g];
g = nil;
The Game objects are about 20[Mbyte].
After performing step 3 I noted that the memory allocated in step 2 (by core data) didn't got released after step 3. If I perform steps 2 and 3 in a loop, the memory keep getting allocated but never released.
I read here that it could be the undo manager keeping this memory alive so I shut it down (in step 1) but it didn't help.
I tried:
[managedObjectContext refreshObject:g mergeChanges:NO];
or:
[managedObjectContext reset];
right after step 3. The memory got deallocated but the object didn't deleted.
I also tried:
[managedObjectContext save:nil];
right after step 3. The memory did not got deallocated.
Is there a way to cause core data to dealloc the memory after deletion?
And in general, is there a way to cause Core Data to keep those heavy objects as less as possible?
Refreshing the object reloads from the persistent store. Resetting removed from memory any changes you have made.
Both of these operations will "forget" the fact that you've deleted the object, since that change is only in memory.
You need to save the context after deleting.
Apparently UIManagedDocument suppose to auto-save the changes and after that to give up the game pointers (causing IOS to dealloc the memory). UIManagedDocument auto save in it's own timing. This timing doesn't include the case above so the memory stayed around.
The workaround was to force UIDocument to save all changes to the persistent store by:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentDirectory = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] firstObject];
NSString *documentName = #"MyDocument";
NSURL *url = [documentDirectory URLByAppendingPathComponent:documentName];
[document saveToURL:url forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) {
if (!success) {
NSLog(#"Failed in saveToURL");
}
}];
After that, the memory deallocated!
I have the following method that uses blocks and completion handlers:
// Returns YES if photo is stored in a virtual vacation.
- (BOOL) photoIsOnVacation
{
__block BOOL photoOnFile = NO;
// Identify the documents folder URL.
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSError *errorForURLs = nil;
NSURL *documentsURL = [fileManager URLForDirectory:NSDocumentDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:NO
error:&errorForURLs];
if (documentsURL == nil) {
NSLog(#"Could not access documents directory\n%#", [errorForURLs localizedDescription]);
} else {
// Retrieve the vacation stores on file.
NSArray *keys = [NSArray arrayWithObjects:NSURLLocalizedNameKey, nil];
NSArray *vacationURLs = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:documentsURL
includingPropertiesForKeys:keys
options:NSDirectoryEnumerationSkipsHiddenFiles
error:nil];
if (!vacationURLs) photoOnFile = NO;
else {
// Search each virtual vacation for the photo.
for (NSURL *vacationURL in vacationURLs) {
NSError *errorForName = nil;
NSString *vacationName = nil;
[vacationURL getResourceValue:&vacationName forKey:NSURLNameKey error:&errorForName];
[VacationHelper openVacationWithName:vacationName usingBlock:^(UIManagedDocument *vacationDocument) {
NSError *error = nil;
NSManagedObjectContext *moc = vacationDocument.managedObjectContext;
// Build fetch request.
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Photo"];
NSString *currentPhotoID = [self.chosenPhoto objectForKey:FLICKR_PHOTO_ID];
request.predicate = [NSPredicate predicateWithFormat:#"unique = %#", currentPhotoID];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"unique" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
// Execute fetch request.
NSArray *checkPhotos = [moc executeFetchRequest:request error:&error];
if (error) {
NSLog(#"Error searching for photo:%#",error);
} else {
Photo *checkPhoto = [checkPhotos lastObject];
if ([checkPhoto.unique isEqualToString:currentPhotoID]) photoOnFile = YES;
}
}];
if (photoOnFile) break;
}
}
}
return photoOnFile;
}
My problem is that photoOnFile is always false because execution reaches the return before the block that contains the fetch request. I've tried embedding the photoOnFile assignment within dispatch_async(dispatch_get_main_queue(),^{ but that hasn't helped. Any guidance appreciated.
Update: here is the reworked code successfully incorporating Ken's recommended solution:
- (void)checkIfPhotoIsOnVacationAndDo:(void(^)(BOOL photoIsOnVacation))completionBlock
{
__block BOOL photoIsOnVacation = NO;
// Identify the documents folder URL.
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSError *errorForURLs = nil;
NSURL *documentsURL = [fileManager URLForDirectory:NSDocumentDirectory
inDomain:NSUserDomainMask
appropriateForURL:nil
create:NO
error:&errorForURLs];
if (documentsURL == nil) {
NSLog(#"Could not access documents directory\n%#", [errorForURLs localizedDescription]);
} else {
// Retrieve the vacation stores on file.
NSArray *keys = [NSArray arrayWithObjects:NSURLLocalizedNameKey, nil];
NSArray *vacationURLs = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:documentsURL
includingPropertiesForKeys:keys
options:NSDirectoryEnumerationSkipsHiddenFiles
error:nil];
if (!vacationURLs) photoIsOnVacation = NO;
else {
// Search each virtual vacation for the photo.
for (NSURL *vacationURL in vacationURLs) {
NSError *errorForName = nil;
NSString *vacationName = nil;
[vacationURL getResourceValue:&vacationName forKey:NSURLNameKey error:&errorForName];
[VacationHelper openVacationWithName:vacationName usingBlock:^(UIManagedDocument *vacationDocument) {
NSError *error = nil;
NSManagedObjectContext *moc = vacationDocument.managedObjectContext;
// Build fetch request.
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Photo"];
NSString *currentPhotoID = [self.chosenPhoto objectForKey:FLICKR_PHOTO_ID];
request.predicate = [NSPredicate predicateWithFormat:#"unique = %#", currentPhotoID];
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"unique" ascending:YES];
request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
// Execute fetch request.
NSArray *checkPhotos = [moc executeFetchRequest:request error:&error];
if (error) {
NSLog(#"Error searching for photo:%#",error);
} else {
Photo *checkPhoto = [checkPhotos lastObject];
if ([checkPhoto.unique isEqualToString:currentPhotoID]) {
photoIsOnVacation = YES;
completionBlock(photoIsOnVacation);
}
}
}];
if (photoIsOnVacation) break;
}
completionBlock(photoIsOnVacation);
}
}
}
Asynchronicity tends to spread. Once you make an API asynchronous, all of its callers have to be redesigned to work asynchronously, too. Therefore, a method like your - (BOOL) photoIsOnVacation is untenable because its interface is synchronous – the caller expects to have an answer as soon as the call completes – but the implementation doesn't work that way.
You have to redesign to something like - (void) checkIfPhotoIsOnVacationAndDo:(void(^)(BOOL photoIsOnVacation))block. That takes a block from the caller and invokes the block with the answer when it is known.
This is what semaphores are for:
bool waitForBlockToExecute()
{
__block bool value = false;
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// sleep for a bit
sleep(1);
value = true;
// notify that the block is finished
dispatch_semaphore_signal(semaphore);
});
// wait for the semaphore
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
dispatch_release(semaphore); // clean up the semaphore
return value;
}
Obviously, the dispatch_async block would be replaced with your callback block, but I assume you get the picture from the above code.
There seem to be some modifications to the NSPersistentStoreCoordinator method is iOS 5.
I am trying to get a prepopulated database ... it doesn't seem to work, no crash but none of the data seems to exist... Any suggestions?
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
{
return __persistentStoreCoordinator;
}
NSURL *storePath = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"DataModel.sqlite"];
/*
Set up the store.
For the sake of illustration, provide a pre-populated default store.
*/
NSFileManager *fileManager = [NSFileManager defaultManager];
// If the expected store doesn't exist, copy the default store.
if (![fileManager fileExistsAtPath:[storePath absoluteString]]) {
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:#"DataModel" ofType:#"sqlite"];
if (defaultStorePath) {
[fileManager copyItemAtPath:defaultStorePath toPath:[storePath absoluteString] error:NULL];
}
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"DataModel.sqlite"];
NSError *error = nil;
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
The problem is in the applicationDocumentsDirectory method that gives wrong absolute string. It is not really wrong, but is not suited for NSFileManager class.
The solution is simple. You need to write another method which I called applicationDocumentsDirectory2.
So first, go to header file of your AppDelegate and declare method:
- (NSString *)applicationDocumentsDirectory2;
Now, go to the .m file, and define a method:
- (NSString *)applicationDocumentsDirectory2 {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
And finally, just change persistentStoreCoordinator method into:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (__persistentStoreCoordinator != nil)
{
return __persistentStoreCoordinator;
}
NSError *error = nil;
NSString *storePath = [[self applicationDocumentsDirectory2] stringByAppendingPathComponent: #"DataModel.sqlite"];
/*
Set up the store.
For the sake of illustration, provide a pre-populated default store.
*/
NSFileManager *fileManager = [NSFileManager defaultManager];
// If the expected store doesn't exist, copy the default store.
if (![fileManager fileExistsAtPath:storePath]) {
NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:#"DataModel" ofType:#"sqlite"];
if (defaultStorePath) {
if(![fileManager copyItemAtPath:defaultStorePath toPath:storePath error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
}
}
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"DataModel.sqlite"];
__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![__persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error])
{
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return __persistentStoreCoordinator;
}
That's it! :)
IfIDieAppDelegate.m
- (void)createEditableCopyOfDatabaseIfNeeded
{
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"DeathDiary.sqlite"];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"IfIDie.sqlite"];
NSLog(#"%#",writableDBPath);
success = [fileManager fileExistsAtPath:writableDBPath];
if (success==YES)
{
NSLog(#"Database Already Exists");
return;
}
else {
NSLog(#"New Database Created");
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"IfIDie.sqlite"];
NSLog(#"Default : %#",defaultDBPath);
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable database file with message '%#'.", [error localizedDescription]);
}
}
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (persistentStoreCoordinator != nil) {
return persistentStoreCoordinator;
}
NSURL *storeUrl = [NSURL fileURLWithPath: [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"IfIDie.sqlite"]];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:nil error:&error]) {
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator;
}
NoteEditController.m
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
if(saveChanges){
// Save any changes to note
if([[noteTextView text] length] > 0){
if(noteToEdit){
// Edit Note
if([[titleField text] length] <= 0)
[noteToEdit setNoteTitle:[noteTextView text]];
else
[noteToEdit setNoteTitle:[titleField text]];
[noteToEdit setNoteText:[noteTextView text]];
} else {
// New Note
Note *newNote = [NSEntityDescription
insertNewObjectForEntityForName:#"Note" inManagedObjectContext:context];
if([[titleField text] length] <= 0)
[newNote setNoteTitle:[noteTextView text]];
else
[newNote setNoteTitle:[titleField text]];
[newNote setNoteText:[noteTextView text]];
NSLog(#"data saved");
}
} else {
// Remove note (zero length)
if(noteToEdit){
[context deleteObject:noteToEdit];
}
}
}
}
Everything seems going ok here but still data is not saving to table.what could be wrong?
is there something with database reload?if, then i m not getting how to resolve.
no error is there.it shows nslog of data saved but not saved to table.
You will need to save the context to actually commit your changes at the end of viewWillDisappear: method
NSError *error = nil;
if (![context save: &error]) {
// Couldn't save
}
I added a new model version, and I set the core data model to use that new version, but I get this error when the application tries to start.
"The managed object model version used to open the persistent store is incompatible with the one that was used to create the persistent store."
I'm guessing the problem is that the current persistent store is the old version of the model. Is there a way to just delete it so it makes a new one? I don't care about saving any of that data.
You have to migrate between versions. According to Apple's docs, if the changes are simple, you can do lightweight migration.
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmLightweight.html#//apple_ref/doc/uid/TP40008426-SW1
Adding these options to the NSPersistentStoreCoordinator seemed to work.
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSURL *url = [applicationFilesDirectory URLByAppendingPathComponent:#"YOURAPP.storedata"];
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType configuration:nil URL:url options:options error:&error]) {
[[NSApplication sharedApplication] presentError:error];
[persistentStoreCoordinator release], persistentStoreCoordinator = nil;
return nil;
}
return persistentStoreCoordinator;
In answer to your question, "Is there a way to delete it so it just makes a new one ?"
Yes.
Just change the persistentStoreCoordinator getter in your App Delegate as follows:
- (NSPersistentStoreCoordinator *) persistentStoreCoordinator {
if (persistentStoreCoordinator) return persistentStoreCoordinator;
NSManagedObjectModel *mom = [self managedObjectModel];
if (!mom) {
NSAssert(NO, #"Managed object model is nil");
NSLog(#"%#:%s No model to generate a store from", [self class], (char *)_cmd);
return nil;
}
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *applicationSupportDirectory = [self applicationSupportDirectory];
NSError *error = nil;
if ( ![fileManager fileExistsAtPath:applicationSupportDirectory isDirectory:NULL] ) {
if (![fileManager createDirectoryAtPath:applicationSupportDirectory withIntermediateDirectories:NO attributes:nil error:&error]) {
NSAssert(NO, ([NSString stringWithFormat:#"Failed to create App Support directory %# : %#", applicationSupportDirectory,error]));
NSLog(#"Error creating application support directory at %# : %#",applicationSupportDirectory,error);
return nil;
}
}
NSURL *url = [NSURL fileURLWithPath: [applicationSupportDirectory stringByAppendingPathComponent: #"storedata"]];
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: mom];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType
configuration:nil
URL:url
options:nil
error:&error]){
// EDIT: if error opening persistent store, remove it and create a new one
if([[error domain] isEqualToString:#"NSCocoaErrorDomain"] && [error code] == 134100) {
NSLog(#"Core Data model was updated. Deleting old persistent store.");
[[NSFileManager defaultManager] removeItemAtURL:url error:nil];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType
configuration:nil
URL:url
options:nil
error:&error]){
[[NSApplication sharedApplication] presentError:error];
[persistentStoreCoordinator release], persistentStoreCoordinator = nil;
return nil;
}
} else {
[[NSApplication sharedApplication] presentError:error];
[persistentStoreCoordinator release], persistentStoreCoordinator = nil;
return nil;
}
//
}
return persistentStoreCoordinator;
}
Figure out where your app stored the document and put it in the trash.
But as a extended comment you may wish to examine the possibilities around both explicit and implicit migration in NSPersistentStoreCoordinator and the options in.
- (NSPersistentStore *)addPersistentStoreWithType:(NSString *)storeType configuration:(NSString *)configuration URL:(NSURL *)storeURL options:(NSDictionary *)options error:(NSError **)error
Depending how different the versions are you can get it to happen automagically by passing NSMigratePersistentStoresAutomaticallyOption & NSInferMappingModelAutomaticallyOption
theres also
- (NSPersistentStore *)migratePersistentStore:(NSPersistentStore *)store toURL:(NSURL *)URL options:(NSDictionary *)options withType:(NSString *)storeType error:(NSError **)error