Core data 从ViewController刷新AppDelegate中的NSPersistentStoreCoordinator
我有一个在AppDelegate中设置PersistentStoreCoordinator的应用程序。我想从保存的sqlite文件列表中加载一个新的sqlite数据库。我很乐意删除现有的持久存储和sqlite文件,并用从表中加载的文件替换sqlite文件。但是,如何从选择新文件的ViewController操作重新加载/刷新PersistentStoreCoordinator?我尝试将AppDelegate设置为ViewController的代理,但这似乎会在应用程序中创建各种循环引用。另外,重新加载PersistentStoreCoordinator的确切方法是什么 我尝试过这段代码,但它只是清除持久存储,而没有使用加载的sqlite文件进行刷新(Working.sqlite是sqlite数据库当前运行版本的名称): 好的-我现在修改了下面的代码,当我选择要加载的行时,我现在在向PSC最后添加新存储时遇到崩溃。错误代码都是空的,所以我不确定失败的是什么。NSLogs显示原始存储已被删除,新版本已被复制Core data 从ViewController刷新AppDelegate中的NSPersistentStoreCoordinator,core-data,nsmanagedobjectcontext,appdelegate,nspersistentstore,Core Data,Nsmanagedobjectcontext,Appdelegate,Nspersistentstore,我有一个在AppDelegate中设置PersistentStoreCoordinator的应用程序。我想从保存的sqlite文件列表中加载一个新的sqlite数据库。我很乐意删除现有的持久存储和sqlite文件,并用从表中加载的文件替换sqlite文件。但是,如何从选择新文件的ViewController操作重新加载/刷新PersistentStoreCoordinator?我尝试将AppDelegate设置为ViewController的代理,但这似乎会在应用程序中创建各种循环引用。另外,重
- (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阶段收到应用程序崩溃的“未解决错误”日志:
按照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();
}
}
最好的答案是在
NSPersistentStoreCoordinator
上执行-removePersistentStore:error:
,然后执行-addPersistentStoreWithType:configuration:configuration URL:options:error:
作为该过程的一部分,我将在NSManagedObjectContext
上执行-reset
,然后发布视图控制器正在侦听的NSNotification
,然后视图控制器可以重新加载其数据
您不需要从磁盘上删除任何文件
更新1
首先,您需要告诉我们崩溃是什么:)
其次,您没有在-removePersistentStore…
上使用error参数,因此可能会在那里遇到错误
用崩溃更新问题,这将有助于解决这个问题
更新2
此代码没有任何意义:
// 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
。谢谢-我尝试从tableview中选择一个保存的sqlite文件,并将该文件(在loadPath)加载为应用程序的工作数据库。在此过程中,我希望覆盖工作文件working.sqlite,并使用从loadPath复制的新版本重新加载核心数据。我不需要刷新特定的加载文件tableview-那只是一个目录列表。到目前为止,我尝试的方法要么导致错误,要么没有数据刷新。事件都是一样的,删除后,将文件移动到位,然后添加并推送访问数据的视图控制器。谢谢-我尝试在编辑的问题中反映您的建议,但我仍然遇到崩溃。我标记了删除错误,您是对的,那里有点不对劲。我已经用崩溃时的有限日志信息编辑了这个问题。非常感谢@Marcus-现在我的问题的最后代码都可以用了。问题是,文件保存在单独的VC中并没有保存MOC更改!我会单独问这个问题。
// 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();
}