I'm using core-data in my app, and I want to start iTunes filesharing in next update, but need to move my apps sqlite database first. I have tried with the code below, but the app crashes on launch. I thought I could just replace the old store url with a new one in NSPersistentStoreCoordinator, where "newDatabasePath" matches the new store url.
then replace the sqlite file with
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//check app has run before and has a current db
if ([saveData boolForKey:@"hasRunBefore"]) {
NSString *oldDatabasePath = [[dirPaths objectAtIndex:0] stringByAppendingPathComponent:@"AppData.sqlite"];
NSString *newDatabasePath = [privateDocsPath stringByAppendingPathComponent:@"AppData.sqlite"];
NSError *error;
if ([fileMgr fileExistsAtPath:newDatabasePath]) {
[fileMgr removeItemAtPath:newDatabasePath error:&error];
[fileMgr copyItemAtPath:oldDatabasePath toPath:newDatabasePath error:&error];
}
[fileMgr removeItemAtPath:oldDatabasePath error:&error];
BOOL databaseMoved = YES;
[saveData setBool:databaseMoved forKey:@"databaseMoved"];
}
}
Thanks
I tried a new approach to solve this with some success, after reading a similar question on here. I tried resetting the coredata stack like so
- (void)resetDatabase {
NSPersistentStore* store = [[__persistentStoreCoordinator persistentStores] lastObject];
NSError *error = nil;
NSURL *storeURL = store.URL;
// release context and model
__managedObjectModel = nil;
__managedObjectContext = nil;
//[__persistentStoreCoordinator removePersistentStore:store error:nil];
__persistentStoreCoordinator = nil;
NSFileManager* fileMgr = [NSFileManager defaultManager];
[fileMgr removeItemAtPath:storeURL.path error:&error];
if (error) {
NSLog(@"filemanager error %@", error);
}
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//create Private Documents Folder
NSArray *libPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libDir = [libPaths objectAtIndex:0];
NSString *privateDocsPath = [libDir stringByAppendingPathComponent:@"Private Documents"];
if (![fileMgr fileExistsAtPath:privateDocsPath])
[fileMgr createDirectoryAtPath:privateDocsPath withIntermediateDirectories:YES attributes:nil error:nil];
NSString *oldDatabasePath = [[dirPaths objectAtIndex:0] stringByAppendingPathComponent:@"AppData.sqlite"];
NSString *newDatabasePath = [privateDocsPath stringByAppendingPathComponent:@"AppData.sqlite"];
BOOL removedItemAtPath = NO;
BOOL copiedItemToPath = NO;
if ([fileMgr fileExistsAtPath:newDatabasePath]) {
DLog(@"DATABASE EXISTS AT PATH");
removedItemAtPath = [fileMgr removeItemAtPath:newDatabasePath error:&error];
if (removedItemAtPath) {
DLog(@"ITEM REMOVED");
}
else
DLog(@"FAILED TO REMOVE ITEM: %@", error);
copiedItemToPath = [fileMgr copyItemAtPath:oldDatabasePath toPath:newDatabasePath error:&error];
if (copiedItemToPath) {
DLog(@"ITEM COPIED");
}
else
DLog(@"FAILED TO COPY ITEM: %@", error);
}
// recreate the stack
__managedObjectContext = [self managedObjectContext];
}
With this approach, the app still throws an exception when trying to load data from the coredata stack when I first launch it, but then subsequently reloads everything ok, and uses the sqlite file from it's new location in "Library/Private Documents"