我在我的应用程序中使用核心数据,我想在下次更新时启动 iTunes 文件共享,但需要先移动我的应用程序 sqlite 数据库。我已尝试使用下面的代码,但应用程序在启动时崩溃。我想我可以在 NSPersistentStoreCoordinator 中用新的商店 url 替换旧的商店 url,其中“newDatabasePath”与新的商店 url 匹配。
然后将sqlite文件替换为
- (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"];
}
}
谢谢
在阅读了一个类似的问题后,我尝试了一种新的方法来解决这个问题并取得了一些成功。我尝试像这样重置coredata堆栈
- (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];
}
使用这种方法,当我第一次启动它时尝试从 coredata 堆栈加载数据时,应用程序仍然会引发异常,但随后会重新加载一切正常,并使用“库/私人文档”中新位置的 sqlite 文件