我有一个应用程序,其中在 AppDelegate 中设置了 PersistentStoreCoordinator。我想从保存的 sqlite 文件列表中加载一个新的 sqlite 数据库。我很高兴删除现有的 Persistent Store 和 sqlite 文件并将 sqlite 文件替换为从表中加载的文件。但是,如何从选择新文件的 ViewController 操作中重新加载/刷新 PersistentStoreCoordinator?我尝试将 AppDelegate 设置为 ViewController 的委托,但这似乎会在应用程序中创建各种循环引用。另外,重新加载 PersistentStoreCoordinator 的精确方法是什么?
我已经尝试过这段代码,但它只是清除了持久存储而不刷新加载的 sqlite 文件(Working.sqlite 是当前运行的 sqlite 数据库版本的名称):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
targetPath = [libraryPath stringByAppendingPathComponent:@"Working.sqlite"];
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
NSPersistentStore *store = [[delegate.persistentStoreCoordinator persistentStores] lastObject];
NSError *error;
NSPersistentStoreCoordinator *storeCoordinator = delegate.persistentStoreCoordinator;
[storeCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:targetPath error:&error];
NSString *loadPath = [workingDirPath stringByAppendingPathComponent:[directoryContent objectAtIndex:indexPath.row]];
NSString *loadName = [[directoryContent objectAtIndex:indexPath.row] stringByDeletingPathExtension];
NSLog(@"selectedPlan is: %@", loadName);
if (![[NSFileManager defaultManager] copyItemAtPath:loadPath toPath:targetPath error:&error]) {
NSLog(@"Error: %@", error);
}
else {
[delegate managedObjectContext];
[delegate managedObjectModel];
[delegate persistentStoreCoordinator];
[self.delegate planWasSelectedOnTheFileTableViewController:self];}
好的 - 我现在修改了下面的代码,当我选择要加载的行时,当我最终将新商店添加到 PSC 时,我现在遇到了崩溃。错误代码都是空的,所以我不确定是什么失败了。NSLogs 显示原始存储已被删除,并复制了新版本。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
targetPath = [libraryPath stringByAppendingPathComponent:@"Working.sqlite"]; AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
NSPersistentStore *store = [[delegate.persistentStoreCoordinator persistentStores] lastObject];
NSError *error;
NSString *loadPath = [workingDirPath stringByAppendingPathComponent:[directoryContent objectAtIndex:indexPath.row]];
NSString *loadName = [[directoryContent objectAtIndex:indexPath.row] stringByDeletingPathExtension];
NSLog(@"selectedPlan is: %@", loadName);
[delegate.persistentStoreCoordinator removePersistentStore:store error:&error];
[[NSFileManager defaultManager] removeItemAtPath:targetPath error:&error];
if ([[NSFileManager defaultManager] fileExistsAtPath:targetPath]){NSLog(@"It's still there!");
}
else {NSLog(@"File deleted");}
[[NSFileManager defaultManager] copyItemAtPath:loadPath toPath:targetPath error:&error];
if ([[NSFileManager defaultManager] fileExistsAtPath:targetPath]){NSLog(@"File Copied");
}
else {NSLog(@"path empty");}
NSURL *storeURL = [NSURL fileURLWithPath:targetPath];
error = nil;
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
[delegate.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]; { NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
[self.delegate planWasSelectedOnTheFileTableViewController:self];}
Marcus - 我认为这反映了您的建议,但我仍然让应用程序在 addPersistentStore 阶段崩溃,并显示“未解决的错误”日志:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
//setting path to current working sqlite file
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
targetPath = [libraryPath stringByAppendingPathComponent:@"Working.sqlite"];
//setting path to selected sqlite file
NSString *loadPath = [workingDirPath stringByAppendingPathComponent:[directoryContent objectAtIndex:indexPath.row]];
NSString *loadName = [[directoryContent objectAtIndex:indexPath.row] stringByDeletingPathExtension];
NSLog(@"selectedPlan is: %@", loadName);
// retrieve the store URL
NSURL * storeURL = [NSURL fileURLWithPath:targetPath];
NSString *storeName = [storeURL absoluteString];
NSLog(@"Persistent Store is: %@", storeName);
if ([[NSFileManager defaultManager] fileExistsAtPath:targetPath]){NSLog(@"It was there before it was deleted");}
// remove the store
NSError *error;
[delegate.persistentStoreCoordinator removePersistentStore:[[delegate.persistentStoreCoordinator persistentStores] lastObject] error:&error];
{NSLog(@"Unresolved error on remove %@, %@", error, [error userInfo]);
abort();}
error = nil;
// remove the store file and check it's gone
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
if ([[NSFileManager defaultManager] fileExistsAtPath:targetPath]){NSLog(@"It's still there!");}
else {NSLog(@"File deleted");}
// copy in new file and check it's there
[[NSFileManager defaultManager] copyItemAtPath:loadPath toPath:targetPath error:&error];
if ([[NSFileManager defaultManager] fileExistsAtPath:targetPath]){NSLog(@"File Copied");}
else {NSLog(@"path empty");}
//re-attach the store
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
[delegate.persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error];
{NSLog(@"Unresolved error on add %@, %@", error, [error userInfo]);
abort();}
}
按照 Marcus 的建议,我在上面修改后的代码中添加了 removePersistentStore 上的错误日志。问题出现在删除操作中。日志文件结束如下:
2013-06-01 01:10:02.478 inControl[1238:907] 持久存储是:file://localhost/var/mobile/Applications/D34C6065-8D59-480F-ABA4-9F10C690F26C/Library/Working.sqlite
2013-06-01 01:10:02.481 inControl[1238:907] 在被删除之前它就在那里
2013-06-01 01:10:02.486 inControl[1238:907] 删除时未解决的错误 (null), (null)
遵循 Marcus 的建议的最终工作代码:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
//setting path to current working sqlite file
NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];
targetPath = [libraryPath stringByAppendingPathComponent:@"Working.sqlite"];
//setting path to selected sqlite file
NSString *loadPath = [workingDirPath stringByAppendingPathComponent:[directoryContent objectAtIndex:indexPath.row]];
NSString *loadName = [[directoryContent objectAtIndex:indexPath.row] stringByDeletingPathExtension];
NSLog(@"selectedPlan is: %@", loadName);
// retrieve the store URL
NSURL * storeURL = [NSURL fileURLWithPath:targetPath];
NSString *storeName = [storeURL absoluteString];
NSLog(@"Persistent Store is: %@", storeName);
if ([[NSFileManager defaultManager] fileExistsAtPath:targetPath]){NSLog(@"It was there before it was deleted");}
// remove the store
NSError *error;
NSPersistentStoreCoordinator *psc = [delegate persistentStoreCoordinator];
NSPersistentStore *ps = [[psc persistentStores] lastObject];
if (![psc removePersistentStore:ps error:&error]) {
NSLog(@"Remove Store Failure: %@\n%@", [error localizedDescription], [error userInfo]);
abort();
} error = nil;
// remove the store file and check it's gone
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:&error];
if ([[NSFileManager defaultManager] fileExistsAtPath:targetPath]){NSLog(@"It's still there!");}
else {NSLog(@"File deleted");}
// copy in new file and check it's there
[[NSFileManager defaultManager] copyItemAtPath:loadPath toPath:targetPath error:&error];
if ([[NSFileManager defaultManager] fileExistsAtPath:targetPath]){NSLog(@"File Copied");}
else {NSLog(@"path empty");}
[delegate.managedObjectContext reset];
//re-attach the store
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
NSLog(@"Add Store Failure: %@\n%@", [error localizedDescription], [error userInfo]);
abort();
}
}