我使用CoreData构建了一个应用程序来保存内容。一切正常。现在我想导出存储数据的SQLite DB文件。
我通过从设备下载容器来检查数据库文件的路径。它似乎是"〜\ Library \ Application Support \ MainData.sqlite"。
文件路径的屏幕截图:
我调用了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共享文件的信息:
但是,下载容器中的MainData.sqlite是最新更新的。最新数据在此文件中,使用DB Browser进行检查。
屏幕截图:容器中的文件信息:
请帮助指出我的代码有什么问题。
添加内容:
感谢@ user2782993引用关于以下主题的Apple答案:https://developer.apple.com/library/content/qa/qa1809/_index.html
我还从苹果库中读到了这个技术Q& A。但是,如何在生成的lazy var persistentContainer
的XCode中实现模式更改选项并不是很清楚。
此外,this thread提到了
为了理智,你应该确保你只有一个连接 执行此操作时持久存储,即只有一个持久存储 单个持久性存储协调器中的实例。
我不确定如何关闭现有连接。有任何想法吗? (斯威夫特更好)
答案 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文件上下文。因此,商店文件包含最新的数据库。"