在应用程序运行时切换 Core Data sqlite 文件?数据不显示

Posted

技术标签:

【中文标题】在应用程序运行时切换 Core Data sqlite 文件?数据不显示【英文标题】:Switch Core Data sqlite file while app is running? Data doesn't show 【发布时间】:2016-11-02 18:14:37 【问题描述】:

我让用户在 ios 设备上通过电子邮件备份和恢复 sqlite 数据库。我成功导出和导入 sqlite 数据库。我的问题是当我想用新文件替换当前的 sqlite 文件时,数据不会自动更新。当我在函数末尾添加一个 exit(0) 时,它会关闭,并且在重新打开应用程序时数据就在那里。这不是一个解决方案,因为它基本上是一个崩溃。这是我用来将一个 sqlite 文件替换为另一个的函数。 注意我已经关闭了日志,所以整个数据库是一个 sqlite 文件 有没有人知道在应用程序运行时用另一个 sqlite 文件替换一个 sqlite 文件的正确方法?谢谢。

- (BOOL)resetApplicationModel 

// ----------------------
// This method removes all traces of the Core Data store and then resets the application defaults
// ----------------------

NSError *_error = nil;
NSURL *_storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Database.sqlite"];

NSPersistentStore *_store = [persistentStoreCoordinator persistentStoreForURL:_storeURL];

// Remove the SQL store and the file associated with it
if ([persistentStoreCoordinator removePersistentStore:_store error:&_error])
    [[NSFileManager defaultManager] removeItemAtPath:_storeURL.path error:&_error];


if (_error) 
    NSLog(@"Failed to remove persistent store: %@", [_error localizedDescription]);
    return NO;


[persistentStoreCoordinator release], persistentStoreCoordinator = nil;
[managedObjectContext release], managedObjectContext = nil;

NSString *applicationDocumentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *originalFile = [applicationDocumentDirectory stringByAppendingPathComponent:@"Database.sqlite"];

NSString *backupDatabaseFolder = [applicationDocumentDirectory stringByAppendingPathComponent:@"Backups"];
NSString *backupFile = [backupDatabaseFolder stringByAppendingPathComponent:[NSString stringWithFormat:@"DatabaseBackup.sqlite"]];

[[NSFileManager defaultManager] copyItemAtPath:backupFile toPath:originalFile error:nil];

// Rebuild the application's managed object context
rootViewController.managedObjectContext = nil;
rootViewController.managedObjectContext = self.managedObjectContext;

return YES;

【问题讨论】:

执行此操作后,您的应用会在某处加载新数据吗? 当我在模拟器上测试时,如果我在函数末尾添加一个 exit(0) ,则会出现新数据。如果我第一次尝试执行此操作时应用程序不在内存中,它也可以工作。如果应用程序在内存中,它不起作用即使我从内存中删除应用程序并重新打开,我也看不到新数据。谢谢。 你没有回答这个问题。运行此代码后,您的应用是否会尝试从新的持久性存储中加载数据? 对不起汤姆。不,它没有。显示的数据是原始的 sqlite 数据,除非应用程序不在内存中,或者我在函数末尾添加 exit(0) 而不是显示新数据。谢谢。 【参考方案1】:

我将假设您的 managedObjectContextpersistentStoreCoordinator 方法遵循典型的方法 - 即在您将它们设置为 nil 之后,再次请求它们将懒惰地重新初始化它们。如果不是这种情况,那么这是第一个问题,即您正在拆除旧的 Core Data 堆栈但没有替换它。

假设这是真的,问题是——正如你在评论中所说——你的应用没有尝试获取新数据。如果您希望应用程序显示新数据......您需要让您的应用程序使用获取请求来请求该数据。您的 UI 不会因为您运行上面的方法而自动更新,您需要做一些事情以使其获取新值。

这样做意味着您需要清除从 Core Data 获取的 每个 对象 - 每个 托管对象以及您可能拥有的任何获取的结果控制器。

【讨论】:

感谢汤姆的反馈。这可能就是为什么当我使用退出或应用程序未激活时它可以工作,因为尚未设置任何内容。明白了,那么我将如何清除每个对象、每个托管对象和获取的结果控制器?有没有一种简单的方法可以做到这一点?谢谢。 任何引用了您获取的内容的变量、属性等都将设置为 nil。这是否容易取决于您的应用的设置方式。 确实,你是对的。根视图控制器管理一个获取的结果控制器,当存储被移除时,该控制器仍然持有对象。清除商店后,我将如何删除并重新加载该控制器?我已经尝试过这种变化,但仍然不断崩溃:rootViewController.managedObjectContext = nil; rootViewController.fetchedResultsController=nil;

以上是关于在应用程序运行时切换 Core Data sqlite 文件?数据不显示的主要内容,如果未能解决你的问题,请参考以下文章

Fetch on Core Data 可以在模拟器上运行,但不能在设备上运行

Core Data 在切换视图时使属性为 NULL

从 Core Data 中删除对象和切换视图控制器时崩溃

从 XML 切换到 SQLite Core Data 存储时都有哪些潜在障碍?

在 Core Data 存储之间切换

在开发过程中切换到使用 Core Data?