提问人:Abv 提问时间:8/14/2021 最后编辑:Abv 更新时间:8/15/2021 访问量:511
如何使用引用使用“外部存储”保存的图像的SQLite文件预加载核心数据?
How to pre-load Core Data with a SQLite file that have references to images that were saved using "external storage"?
问:
我的目标是在首次启动应用程序时预加载 Core Data。到目前为止,我运行了一个模拟,并用数据填充了核心数据。(我已经选中了“允许外部存储”)。
我进入application_support并复制了:MyApp.sqlite-wal、MyApp.sqlite-shm、.MyApp_SUPPORT/_EXTERNAL_DATA/ 和 MyApp.sqlite。
然后,我在我的应用程序包中添加了 MyApp.sqlite 文件,并在我的应用程序委托中添加了以下代码:
lazy var persistentContainer: NSPersistentContainer = {
let modelName = "MyApp"
var container: NSPersistentContainer!
container = NSPersistentContainer(name: modelName)
// Preloading
let appName: String = "MyApp"
var persistentStoreDescriptions: NSPersistentStoreDescription
let storeUrl = self.getDocumentsDirectory().appendingPathComponent("MyApp.sqlite")
if !FileManager.default.fileExists(atPath: (storeUrl.path)) {
let seededDataUrl = Bundle.main.url(forResource: appName, withExtension: "sqlite")
try! FileManager.default.copyItem(at: seededDataUrl!, to: storeUrl)
}
let description = NSPersistentStoreDescription()
description.shouldInferMappingModelAutomatically = true
description.shouldMigrateStoreAutomatically = true
description.url = storeUrl
container.persistentStoreDescriptions = [description]
//End Preloading
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
它可以工作,但看起来找不到保存在外部存储中的图像。它们存在于 中。MyApp_SUPPORT/_EXTERNAL_DATA作为参考。 我应该在哪里添加引用?
加载一切是我的目标。
答:
如果您在某个目录(此处为应用程序包)中有一个名为外部二进制存储的文件,则 Core Data 会将这些文件放在名为 .您需要以递归方式复制该目录及其子目录中的所有内容。MyApp.sqlite
.MyApp_SUPPORT/_EXTERNAL_DATA/
但是,使用该路径并不是一个好主意,因为它没有记录,并且可能会在没有警告的情况下更改。此外,如果存在,这将错过 和 。MyApp.sqlite-wal
MyApp.sqlite-shm
更好的主意是将种子存储放在自己的自定义目录中,然后从该目录中复制所有内容。您将拥有一个名为 的目录,其中包含 。它还将包含Core Data需要的所有其他内容,例如外部二进制文件。使用相同的函数复制目录(因为它会递归复制每个文件),你应该没问题。MyApp.sqlite
MyAppSeedData
MyApp.sqlite
FileManager
MyAppSeedData
复制文件夹的代码如下所示:
if let sourceDirURL = Bundle.main.url(forResource: "Source Folder", withExtension: nil) {
let destinationDirURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("TestFolder")
if !FileManager.default.fileExists(atPath: destinationDirURL.path) {
do {
try FileManager.default.copyItem(at: sourceDirURL, to: destinationDirURL)
} catch {
print("Error copying directory: \(error)")
}
}
}
然后,您可以将 SQLite 文件名添加到末尾,并将其用于 Core Data。destinationDirURL
评论
第 1 步:创建“MyAppSeedData”目录并将 MyApp.sqlite、MyApp_SUPPORT、MyApp.sqilte-smh、MyApp.sqilte-wal 文件粘贴到其中。
第 2 步:将 MyAppSeedData 拖到 AppDelegate 下的捆绑包中,然后勾选添加目标框。
第 3 步:这些函数必须位于 AppDelegate 文件中:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
//If first launch condition == true {
seedData()
//}
return true
}
func seedData() {
let fm = FileManager.default
//Destination URL: Application Folder
let libURL = fm.urls(for: .libraryDirectory, in: .userDomainMask).first!
let destFolder = libURL.appendingPathComponent("Application Support").path
//Or
//let l1 = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last!
//
//Starting URL: MyAppSeedData dir
let folderPath = Bundle.main.resourceURL!.appendingPathComponent("MyAppSeedData").path
let fileManager = FileManager.default
let urls = fileManager.urls(for: .applicationSupportDirectory, in: .userDomainMask)
if let applicationSupportURL = urls.last {
do{
try fileManager.createDirectory(at: applicationSupportURL, withIntermediateDirectories: true, attributes: nil)
}
catch{
print(error)
}
}
copyFiles(pathFromBundle: folderPath, pathDestDocs: destFolder)
}
func copyFiles(pathFromBundle : String, pathDestDocs: String) {
let fm = FileManager.default
do {
let filelist = try fm.contentsOfDirectory(atPath: pathFromBundle)
let fileDestList = try fm.contentsOfDirectory(atPath: pathDestDocs)
for filename in fileDestList {
try FileManager.default.removeItem(atPath: "\(pathDestDocs)/\(filename)")
}
for filename in filelist {
try? fm.copyItem(atPath: "\(pathFromBundle)/\(filename)", toPath: "\(pathDestDocs)/\(filename)")
}
} catch {
print("Error info: \(error)")
}
}
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
let modelName = "MyApp"
var container: NSPersistentContainer!
container = NSPersistentContainer(name: modelName)
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
评论