Core data 从ViewController刷新AppDelegate中的NSPersistentStoreCoordinator

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的代理,但这似乎会在应用程序中创建各种循环引用。另外,重

我有一个在AppDelegate中设置PersistentStoreCoordinator的应用程序。我想从保存的sqlite文件列表中加载一个新的sqlite数据库。我很乐意删除现有的持久存储和sqlite文件,并用从表中加载的文件替换sqlite文件。但是,如何从选择新文件的ViewController操作重新加载/刷新PersistentStoreCoordinator?我尝试将AppDelegate设置为ViewController的代理,但这似乎会在应用程序中创建各种循环引用。另外,重新加载PersistentStoreCoordinator的确切方法是什么

我尝试过这段代码,但它只是清除持久存储,而没有使用加载的sqlite文件进行刷新(Working.sqlite是sqlite数据库当前运行版本的名称):

好的-我现在修改了下面的代码,当我选择要加载的行时,我现在在向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阶段收到应用程序崩溃的“未解决错误”日志:

按照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();
}