我有一个应用程序,其中PersistentStoreCoordinator在AppDelegate中设置。我想从已保存的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时,我现在遇到了崩溃。错误代码都是null,所以我不确定什么是失败的。 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] Persistent Store是: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();
}
}
答案 0 :(得分:2)
最佳答案是在-removePersistentStore:error:
上执行NSPersistentStoreCoordinator
然后执行-addPersistentStoreWithType: configuration: configuration URL: options: error:
作为该过程的一部分,我会在-reset
上执行NSManagedObjectContext
,然后发布您的视图控制器正在侦听的NSNotification
,然后您的视图控制器就可以重新加载其数据。
您无需从磁盘中删除任何文件。
首先,您需要告诉我们崩溃是什么:)
其次,您没有在-removePersistentStore...
上使用错误参数,因此您可能会在那里收到错误。
使用崩溃更新问题,这将有助于对此进行排序。
这段代码没有任何意义:
// 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;
如果这是准确的,那就错了。它应该是:
NSError *error;
NSPersistentStoreCoordinator *psc = [delegate persistentStoreCoordinator];
NSPersistentStore *ps = [[psc persistentStores] lastObject];
if (![psc removePersistentStore:ps error:&error]) {
NSLog(@"Failure: %@\n%@", [error localizedDescription], [error userInfo]);
abort();
}
请勿回复错误以确定失败,请检查通话中返回的BOOL
。