Close and Re-open or refresh downloaded database - ios

I'm looking for a easy solution to close my database et re-open it.
My App is using an database (CoreData) with formulas, then, when new formulas are available, my App, will download the full database and replace the actual.
This part is working well. But, once downloaded, I'd like to refresh a TableView with the new Database. I checked on the website and internet but, I didn't find answer.
Seems this is linked to the Persistent but not sure.
So I tried to reset my context but, my TableView is only updated once App been closed and re opened.
So, I'd like to know if you have time to give me an example of how to refresh or even close and re open the database.
Thanks in advance for your support.
NSData *fetchedData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"u189496386:xxxxx#xxxxx.com:21/DataBase.sqlite"]];
NSUInteger length = [fetchedData length];
ProgressDownload.progress = 0.5f;
if(length < 1)
{
ContactServer.text = #"Error downloading DataBase or Network access, please check your connection";
}
else
{
ContactServer.text = #"Server contacted, download in progress";
}
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath = [documentsPath stringByAppendingPathComponent:#"DataBase.sqlite"];
testEcriture = [fetchedData writeToFile:filePath atomically:YES];
if(testEcriture == YES)
{
ContactServer.text = #"Database updated";
ProgressDownload.progress = 1.0f;
}
Then, once back to the first view, the )viewDidLoad is executed, but it seems the content didn't changed.
mesProduits = [[NSMutableArray alloc] init];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"Projector" inManagedObjectContext:context];
NSFetchRequest *frequest = [[NSFetchRequest alloc] init];
[frequest setEntity:entityDesc];
NSSortDescriptor *sortDescription = [[NSSortDescriptor alloc] initWithKey:#"model" ascending:YES];
[frequest setSortDescriptors:#[sortDescription]];
NSError *error;
NSArray *matchingData = [context executeFetchRequest:frequest error:&error];

Your managed object context has a property, persistentStoreCoordinator, which provides a reference to the persistent store coordinator underpinning the database. The PSC accesses the persistent store to read and write the data.
So, to replace the database you would do something along these lines:
NSManagedObjectContext *context = self.context;
NSError *error = nil;
// Save the context before doing anything else.
if (![context save:&error]) {
NSLog(#"Error saving context: %#, %#", error, [error userInfo]);
abort();
}
// Get URL to the current database...
NSPersistentStoreCoordinator *psc = context.persistentStoreCoordinator;
NSPersistentStore *currentStore = psc.persistentStores[0];
NSURL *currentURL = currentStore.URL;
// Get URL to the new database...
NSURL *appDocs = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *newDatabaseURL = [appDocs URLByAppendingPathComponent:#"DataBase.sqlite"];
// Disconnect from the current database...
if (![psc removePersistentStore:currentStore error:&error]) {
NSLog(#"Error removing store: %#, %#", error, [error userInfo]);
abort();
}
// Replace the old database with the new, keeping a backup copy...
if (![[NSFileManager defaultManager] replaceItemAtURL:currentURL withItemAtURL:newDatabaseURL backupItemName:#"DataBase.backup" options:(NSFileManagerItemReplacementUsingNewMetadataOnly | NSFileManagerItemReplacementWithoutDeletingBackupItem) resultingItemURL:nil error:&error]) {
NSLog(#"Error replacing the store: %#, %#", error, [error userInfo]);
abort();
}
// Open the new database...
NSString *failureReason = #"There was an error creating or loading the application's saved data.";
if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:currentURL options:nil error:&error]) {
// Report any error we got.
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSLocalizedDescriptionKey] = #"Failed to initialize the application's saved data";
dict[NSLocalizedFailureReasonErrorKey] = failureReason;
dict[NSUnderlyingErrorKey] = error;
error = [NSError errorWithDomain:#"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
The various error cases should be properly handled, I've just logged and aborted for demonstration purposes. Be aware that your new database must match the schema for the existing database, or you will get an error. And obviously anything previously written to your old database is lost.

Related

Core Data Set Up, Saving Duplicates and Returning Empty Objects

ANSWERED Q2 by FIXING Q1, FEEL FREE TO EXPLAIN IF YOU KNOW WHY
Full disclosure, I dabble in Objective C so this could be painfully obvious but I could not find similar problems or more accurately answers to similar problems.
I'm writing a very simple app and I am learning about core data and I have a couple of issues
Q.1 Has been answered so here is Q.2
Q2. When fetching from Core Data I retrieve empty objects?
With the Data Controller being the same as the above question I call
- (NSMutableArray*) returnTimers
{
[self initilizeDataLayer];
NSMutableArray *listOfTimers = [[NSMutableArray alloc]init];
NSFetchRequest *request = [[NSFetchRequest alloc]initWithEntityName:#"Timer"];
NSError *error = nil;
NSArray *listOfTimersRaw = [myDataController.managedObjectContext executeFetchRequest:request error:&error];
if (error != nil) {
//Deal with failure
}
else {
//Deal with success
listOfTimers = [NSMutableArray arrayWithArray:listOfTimersRaw];
}
return listOfTimers;
}
This correctly retrieves 2 objects but they are empty?
Again this is experimentation so may be arse ways but I have to learn somehow.....Any help would be greatly appreciated.
BELOW HERE HAS BEEN ANSWERED THANKS
Q1. Saving Objects to Core Data creates a blank row in sqlite db - Why?
I have set up a DataController Object like in the Apple Docs
- (void)initializeCoreData
{
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:#"WorkRestWork" withExtension:#"momd"];
NSManagedObjectModel *mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSAssert(mom != nil, #"Error initializing Managed Object Model");
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[moc setPersistentStoreCoordinator:psc];
[self setManagedObjectContext:moc];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentsURL = [[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *storeURL = [documentsURL URLByAppendingPathComponent:#"WorkRestWork.sqlite"];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
NSError *error = nil;
NSPersistentStoreCoordinator *psc = [[self managedObjectContext] persistentStoreCoordinator];
NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:_options error:&error];
NSAssert(store != nil, #"Error initializing PSC: %#\n%#", [error localizedDescription], [error userInfo]);
});
}
Then I call this method
- (BOOL) addTimerWithName: (NSString*)timerName
{
[self initilizeDataLayer];
Timer *newTimer = [NSEntityDescription insertNewObjectForEntityForName:#"Timer" inManagedObjectContext:myDataController.managedObjectContext];
newTimer = [NSEntityDescription insertNewObjectForEntityForName:#"Timer" inManagedObjectContext:myDataController.managedObjectContext];
newTimer.name = timerName;
[myDataController.managedObjectContext insertObject:newTimer];
NSError *error = nil;
if ([myDataController.managedObjectContext save:&error] == NO) {
NSAssert(NO, #"Error saving context: %#\n%#", [error localizedDescription], [error userInfo]);
return NO;
}
return YES;
}
And Finally
[cdh addTimerWithName:#"A TEST"];
When I check check the .sqlite file using Base there are 2 rows, one with "A TEST" as the Name and the other empty which is confusing me
Ad Q1.
You are inserting two timers here. However you assign a name just to the second one. First one has no name cause you never set it. Here's your code with some comments:
// Inserts first timer
Timer *newTimer = [NSEntityDescription insertNewObjectForEntityForName:#"Timer" inManagedObjectContext:myDataController.managedObjectContext];
// Inserts second timer
newTimer = [NSEntityDescription insertNewObjectForEntityForName:#"Timer" inManagedObjectContext:myDataController.managedObjectContext];
// Sets name of the second timer
newTimer.name = timerName;

copying an sqlite file from one project to another

Following this tutorial http://www.raywenderlich.com/12170/core-data-tutorial-how-to-preloadimport-existing-data-updated, I created an empty command line application using core data to seed a database which I subsequently moved (by taking the quizgeodata.sqlite file) over to an ios application I am building. The only other step the tutorial lists for making it work is to add this code to the persistantStoreCoordinator in app delegate
if (![[NSFileManager defaultManager] fileExistsAtPath:[storeURL path]]) {
NSURL *preloadURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"quizgeodata" ofType:#"sqlite"]];
NSError* err = nil;
if (![[NSFileManager defaultManager] copyItemAtURL:preloadURL toURL:storeURL error:&err]) {
NSLog(#"Oops, could copy preloaded data");
}
}
(Previous steps included taking the class files (that correspond to the entities) and the ...xcdatamodel.d file into the empty command line application to make sure that the schemas would be the same). When I run the code in the empty command line application, it shows the fetched data that I imported in the log statements, so I assume by copying the quizgeodata.sqlite back to the ios application and adding that one bit of code in the persistent store coordinator, then the following code (in viewDidLoad) should fetch the data from core data, but the log statements are showing that no data's been retrieved. The log of the error in the code below says 'null' (meaning no error I assume) and when I ask xCode to print the sql statements it shows this in the console
2014-04-17 16:11:57.477 qbgeo[767:a0b] CoreData: annotation: total fetch execution time: 0.0026s for 0 rows.
so obviously there's no data in the sqlite file that I copied over. Can you explain what I might need to do to get it working?
Please note that I ran Project > Clean several times so that is not the issue
from ViewDidLoad
id delegate = [[UIApplication sharedApplication] delegate];
self.managedObjectContext = [delegate managedObjectContext];
NSError *error;
if (![self.managedObjectContext save:&error]) {
NSLog(#"Whoops, couldn't save: %#", [error localizedDescription]);
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:#"Sportsquiz" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSLog(#"error %#", [error description]);
NSArray *messedUpObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
for (Sportsquiz *info in messedUpObjects) {
NSLog(#"correctAnswer %#", [info valueForKey:#"question"]);
NSLog(#"correctAnswer %#", [info valueForKey:#"correctAnswer"]);
}
Let's try:
The original project:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"TinMung.sqlite"];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSMutableDictionary *pragmaOptions = [NSMutableDictionary dictionary];
/*ATTETION: disable WAL mode*/
[pragmaOptions setObject:#"DELETE" forKey:#"journal_mode"];
NSNumber *optionYes = [NSNumber numberWithBool:YES];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
pragmaOptions, NSSQLitePragmasOption,
optionYes,NSMigratePersistentStoresAutomaticallyOption ,nil];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
abort();
}
return _persistentStoreCoordinator;
}
Copy sqlite file to new project and fetch. I think it will work.

RestKit saveToPersistentStore doesnt work

I am using RestKit for my rest implementation. I fetch the data from the server and upon receiving it, I call saveToPersistentStore which is successful as well but when I turn off internet and load that page again, it doesnt find any data in the store.
Here is the initialization flow -
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"Storage" ofType:#"momd"]];
// NOTE: Due to an iOS 5 bug, the managed object model returned is immutable.
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
// Initialize the Core Data stack
[managedObjectStore createPersistentStoreCoordinator];
NSPersistentStore __unused *persistentStore = [managedObjectStore addInMemoryPersistentStore:&error];
NSAssert(persistentStore, #"Failed to add persistent store: %#", error);
[managedObjectStore createManagedObjectContexts];
// Set the default store shared instance
[RKManagedObjectStore setDefaultStore:managedObjectStore];
I use the mainQueue for everythng -
controller.managedObjectContext = managedObjectStore.mainQueueManagedObjectContext;
This is the function which does the fetch:
[CMLRKSharedManager getNewsForUser:userProfile
urlParams:dict
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
[self.tableView reloadData];
NSLog(#"Fetched object count %lu %# %#", (unsigned long)self.fetchedResultsController.fetchedObjects.count , self.fetchedResultsController, self.fetchedResultsController.managedObjectContext);
NSManagedObjectContext *managedObjCtx = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
NSError *executeError = nil;
if(![managedObjCtx saveToPersistentStore:&executeError]) {
NSLog(#"Failed to save to data store");
}
else
NSLog(#"SAVE SUCCESSFUL");
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
[self.tableView reloadData];
}];
}
Output:
2014-04-02 22:24:01.547 Fetched object count 4
2014-04-02 22:24:01.555 SAVE SUCCESSFUL
Now I kill the app, turn off wifi and launch app again. The table is now blank and I see that the fetchResultsController is seeing 0 items in console log
Apr 2 22:24:36 : In numberOfRows Fetched object count 0
I'm not sure why...
#wain I update the code as follows -
NSError *error = nil;
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"Cover" ofType:#"momd"]];
// NOTE: Due to an iOS 5 bug, the managed object model returned is immutable.
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
// Initialize the Core Data stack
[managedObjectStore createPersistentStoreCoordinator];
Commented these 2 lines
// NSPersistentStore __unused *persistentStore = [managedObjectStore addInMemoryPersistentStore:&error];
// NSAssert(persistentStore, #"Failed to add persistent store: %#", error);
//
Instead added the sqlite db but now the app crashed
BOOL success = RKEnsureDirectoryExistsAtPath(RKApplicationDataDirectory(), &error);
if (! success) {
RKLogError(#"Failed to create Application Data Directory at path '%#': %#", RKApplicationDataDirectory(), error);
}
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:#"Store.sqlite"];
NSPersistentStore *persistentStore = [managedObjectStore addSQLitePersistentStoreAtPath:path fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error];
if (! persistentStore) {
RKLogError(#"Failed adding persistent store at path '%#': %#", path, error);
}
From your description, the issue is that you only have an in-memory store:
[managedObjectStore addInMemoryPersistentStore:&error];
so nothing is saved to disk. You should change this so that you are using an SQLite store. This will save data to disk and generally work better in most usage scenarios.

How to create two persistent stores in one persistent store coordinator

I need to create two persistent stores, each with their own entities, with one persistent store coordinator. The hard part is, I want one persistent store to be linked to iCloud, but the other to only be a local store. I have read about making different configurations for the managed object model, but how do I fetch entities from the local store, rather than the iCloud enabled store? Here is my code so far, Am I headed in the right direction?:
NSMutableDictionary *options = [NSMutableDictionary dictionary];
[options setValue:[NSNumber numberWithBool:YES] forKey:NSMigratePersistentStoresAutomaticallyOption];
[options setValue:[NSNumber numberWithBool:YES] forKey:NSInferMappingModelAutomaticallyOption];
NSURL *cloudURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (cloudURL)
{
NSLog(#"iCloud enabled: %#", cloudURL);
cloudURL = [cloudURL URLByAppendingPathComponent:#"FSListen"];
[options setValue:kICloudContentNameKey forKey:NSPersistentStoreUbiquitousContentNameKey];
[options setValue:cloudURL forKey:NSPersistentStoreUbiquitousContentURLKey];
}
else
{
NSLog(#"iCloud is not enabled");
}
// create the persistent store that will be connected to iCloud for favorites
NSURL *iClouldSoreURL= [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
iClouldSoreURL = [iClouldSoreURL URLByAppendingPathComponent:#"FSListen-iCloud.sqlite"];
NSError *error = nil;
NSPersistentStoreCoordinator *coordinator = [self.managedObjectContext persistentStoreCoordinator];
NSPersistentStore *store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:#"Default"
URL:iClouldSoreURL
options:options
error:&error];
if (!store)
{
NSLog(#"Error adding persistent store to coordinator %#\n%#", [error localizedDescription], [error userInfo]);
//Present a user facing error
}
// create the persistent store that will not be connected to iCloud for downloads
NSError *downloadsStoreError = nil;
NSURL *downloadsStoreURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
downloadsStoreURL = [downloadsStoreURL URLByAppendingPathComponent:#"FSListen-Downloads.sqlite"];
NSPersistentStore *downloadsStore = [coordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:#"Downloads"
URL:downloadsStoreURL
options:nil
error:&downloadsStoreError];
if (!downloadsStore)
{
NSLog(#"ERROR CREATING DOWNLOADS STORE %#", downloadsStoreError.localizedDescription);
}
In my managed object model, I have one configuration with an entity called 'downloads' that I only want to be saved locally, but it is also in the default configuration, which I want to link to iCloud. How do I make sure I am saving my entities in the correct configuration?

SQLite Error 266 on CoreData DB

With my most recent app update, I have started to see very inconsistent SQLite errors when saving my database. These are happening with multiple users, so it is not just the same user crashing repeatedly (though it has happened for the same user multiple times). I am getting error 266, which is SQLITE_IOERR_READ. I haven't found anyone else running into this error, so not sure why I'm getting it.
00:04:18:25 $ -[AppDelegate saveContext] line 328 $ Unresolved error Error Domain=NSCocoaErrorDomain Code=266 "The operation couldn’t be completed. (Cocoa error 266.)" UserInfo=0x1dd141b0 {NSSQLiteErrorDomain=266, NSFilePath=/var/mobile/Applications/[omitted], NSPOSIXErrorDomain=1, NSUnderlyingException=I/O error for database at /var/mobile/Applications/[omitted]. SQLite error code:266, 'not an error' errno:1}, {
* 00:04:18:25 NSFilePath = "/var/mobile/Applications/[omitted].sqlite";
* 00:04:18:25 NSPOSIXErrorDomain = 1;
* 00:04:18:25 NSSQLiteErrorDomain = 266;
* 00:04:18:25 NSUnderlyingException = "I/O error for database at /var/mobile/Applications/[omitted].sqlite. SQLite error code:266, 'not an error' errno:1";
* 00:04:18:25 }
EDIT
Here is the core-data related code (most of it standard boilerplate):
/**
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 by merging all of the models found in the application bundle.
*/
- (NSManagedObjectModel *)managedObjectModel {
if (managedObjectModel != nil) {
return managedObjectModel;
}
//managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain];
// See http://iphonedevelopment.blogspot.com.au/2009/09/core-data-migration-problems.html
NSString *path = [[NSBundle mainBundle] pathForResource:#"modelDB" ofType:#"momd"];
NSURL *momURL = [NSURL fileURLWithPath:path];
managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:momURL];
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;
}
NSString *storePath = [[Utils documentsDirectory] stringByAppendingPathComponent: #"modelDB.sqlite"];
NSURL *storeUrl = [NSURL fileURLWithPath: storePath];
NSError *error = nil;
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]];
// Allow inferred migration from the original version of the application.
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) {
// Handle the error.
CLS_LOG(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
//Turn on complete file protection (encrypts files when phone is locked using device pin)
NSDictionary *fileAttributes = [NSDictionary dictionaryWithObject:NSFileProtectionComplete forKey:NSFileProtectionKey];
if(![[NSFileManager defaultManager] setAttributes:fileAttributes ofItemAtPath:storePath error:&error])
{
//handle error
}
return persistentStoreCoordinator;
}
When a user logs out, this is called to remove the model store:
- (NSPersistentStoreCoordinator *)resetPersistentStore
{
NSError *error = nil;
if ([persistentStoreCoordinator persistentStores] == nil)
return [self persistentStoreCoordinator];
[managedObjectContext release];
managedObjectContext = nil;
//If there are many stores, this could be an issue
NSPersistentStore *store = [[persistentStoreCoordinator persistentStores] lastObject];
if (![persistentStoreCoordinator removePersistentStore:store error:&error])
{
CLS_LOG(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
// Delete file
if ([[NSFileManager defaultManager] fileExistsAtPath:store.URL.path]) {
if (![[NSFileManager defaultManager] removeItemAtPath:store.URL.path error:&error])
{
CLS_LOG(#"Unresolved error %#, %#", error, [error userInfo]);
abort();
}
}
// Delete the reference to non-existing store
[persistentStoreCoordinator release];
persistentStoreCoordinator = nil;
NSPersistentStoreCoordinator *r = [self persistentStoreCoordinator];
return r;
}
My app has a single store, so I don't think NSPersistentStore *store = [[persistentStoreCoordinator persistentStores] lastObject]; would cause an issue.
A little late to respond, but I noticed that this error almost always occurred when our app had been pushed to the background.
When creating the persistentStoreCoordinator you may need to set the NSPersistentStoreFileProtectionKey option to NSFileProtectionCompleteUntilFirstUserAuthentication instead of NSFileProtectionComplete.
Note that this slightly elevates the security risk so you may want to consider if this is necessary in your app.
Are you sure that the database is correctly opened / closed at everytime? It can be a problem due to a file open while it was uncorrectly closed

Resources