无法在Swift中获取最新的CoreData DB文件

时间:2018-01-14 08:46:52

标签: ios swift sqlite core-data

我使用CoreData构建了一个应用程序来保存内容。一切正常。现在我想导出存储数据的SQLite DB文件。

我通过从设备下载容器来检查数据库文件的路径。它似乎是"〜\ Library \ Application Support \ MainData.sqlite"。

文件路径的屏幕截图:

enter image description here

我调用了shareDatabase()来使用AirDrop与我的Mac共享数据库文件,它正常工作:

func shareDatabase() {
    try? (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext.save()
    let fileName = "MainData.sqlite"
    let filePath = URL(fileURLWithPath: NSHomeDirectory()).appendingPathComponent("Library").appendingPathComponent("Application Support").appendingPathComponent(fileName)

    let activityVC = UIActivityViewController(activityItems: [filePath], applicationActivities: nil)
    present(activityVC, animated: true, completion: nil)
}

奇怪的是,转移的MainData.sqlite不是最新版本,而是昨天修改日期的版本。我还用DB Browser打开了文件。它不包含最新数据。

屏幕截图:AirDrop共享文件的信息:

enter image description here

但是,下载容器中的MainData.sqlite是最新更新的。最新数据在此文件中,使用DB Browser进行检查。

屏幕截图:容器中的文件信息:

enter image description here

请帮助指出我的代码有什么问题。

添加内容:

感谢@ user2782993引用关于以下主题的Apple答案:https://developer.apple.com/library/content/qa/qa1809/_index.html

我还从苹果库中读到了这个技术Q& A。但是,如何在生成的lazy var persistentContainer的XCode中实现模式更改选项并不是很清楚。

此外,this thread提到了

  

为了理智,你应该确保你只有一个连接   执行此操作时持久存储,即只有一个持久存储   单个持久性存储协调器中的实例。

我不确定如何关闭现有连接。有任何想法吗? (斯威夫特更好)

1 个答案:

答案 0 :(得分:-1)

尝试使用它:

https://stackoverflow.com/a/18870738/2782993

或者这个:

https://stackoverflow.com/a/20252663/2782993

检查出来:

http://pinkstone.co.uk/how-to-remove-wal-files-in-core-data/

摘录:

"自iOS 7和OS X 10.9起,SQLite Stores中的默认日志记录模式为WAL。除了主存储文件,您还可以找到与存储文件大小相同(或更大)的WAL文件,以及不太重要的SHM文件。

在此实施之前,很容易保存上下文,提取商店文件并将其作为预制数据存储应用程序发送。这是不可能的,因为默认情况下所有数据更改都写入WAL文件,不与主存储文件同步。

如果您没有随应用程序发送预先制作的商店文件,这不是问题,但如果您这样做,那么这种“改进”就会破坏您提供预先写好的数据存储的方式。

幸运的是,我们可以通过在创建NSPersistentStoreCoordinator时传递选项来关闭整个WAL业务。"

以下是关于该主题的Apple答案:

https://developer.apple.com/library/content/qa/qa1809/_index.html

请注意,同步WAL数据称为检查点操作。 重要部分是粗体

摘录:

"答:发生故障是因为Core Data SQLite存储的默认日记模式已更改为iOS 7和OS X Mavericks中的预写日志(WAL)。使用WAL模式,Core Data保持主存储文件不变,并将事务附加到同一位置的-wal文件中。保存Core Data上下文后,不会删除-wal文件,并且该文件中的数据也不会合并到存储文件中。因此,简单地制作商店文件的副本可能会导致数据丢失和不一致。

...

要安全地备份和还原Core Data SQLite存储,您可以执行以下操作:

使用以下NSPersistentStoreCoordinator类方法而不是文件系统API来备份和还原Core Data存储:

- (NSPersistentStore *)migratePersistentStore:(NSPersistentStore *)store toURL:(NSURL *)URL options:(NSDictionary *)options withType:(NSString *)storeType error:(NSError **)error

请注意,这是我们推荐的选项。

如果必须复制存储文件,则在将存储添加到持久性存储协调器时更改为回滚日记模式。清单1是显示如何执行此操作的代码:

清单1添加持久存储时使用回滚日记模式

NSDictionary *options = @{NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}};
if (! [persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                        configuration:nil
                                        URL:storeURL
                                        options:options
                                        error:&error]) {
    // error handling.
}

对于加载了WAL模式的商店,如果主存储文件和相应的-wal文件都存在,则使用回滚日记模式将商店添加到持久存储协调器将强制Core Data执行检查点操作,它将-wal文件中的数据合并到存储文件中。这实际上是执行检查点操作的核心数据方式。另一方面,如果-wal文件不存在,使用此方法添加商店不会导致任何异常,但事务记录在丢失的-wal文件中将丢失。 将主存储文件和-wal文件捆绑到文档包中,并将它们作为单个项目进行操作。 有关默认日记记录模式更改的详细信息,请参阅WWDC 2013会话207核心数据和iCloud中的新功能。

注意:在iOS 6.x和Mountain Lion中,默认为回滚日记模式,其中Core Data创建-journal文件以临时存储事务,更新主存储文件并在保存后删除-journal文件上下文。因此,商店文件包含最新的数据库。"