请参阅以下更新:
有很多类似的问题,但似乎没有一个问题可以为我充分回答,所以任何帮助都将受到赞赏。
我有一个预装的数据库,我在一个单独的应用程序中创建。如果这是第一次运行,则将数据库复制到文档目录中。 我可以从日志中看到数据库位于预期的位置:
AppDelegate urls: [file:///Volumes/HD1%20-%20DATA/Users/david/Library/Developer/CoreSimulator/Devices/8B0E16F5-B739-4299-9B4D-E6A3C8C92E55/data/Containers/Data/Application/B8A87853-6FEB-4532-83EF-AB08985F2B43/Documents/]
通过使用SQLiteManager,我可以验证数据库是否按预期保存数据。
我的CoreData对象图是:
但是,当我执行获取请求时,结果为nil。
这是获取请求:
func testLetters() {
print(#function)
let moc = coreDataStack.persistentContainer.viewContext
let letterFetch = NSFetchRequest<NSFetchRequestResult>(entityName: "LetterEntity")
do {
let fetchedLetters = try moc.fetch(letterFetch) as! [LetterEntity]
print(#function, "letter: ", fetchedLetters)
} catch {
fatalError("Failed to fetch employees: \(error)")
}
}
我的App Delegate外部有一个核心数据堆栈,如下所示:
import UIKit
import CoreData
class CoreDataStack {
static let instance = CoreDataStack()
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "GuessGreek")
let directoryUrls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let applicationDocumentDirectory = directoryUrls[0]
let storeUrl = applicationDocumentDirectory.appendingPathComponent("GuessGreek.sqlite")
container.loadPersistentStores(completionHandler: { (storeUrl, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
return container
}()
func saveContext() {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch let error as NSError {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
}
}
}
同样,欢迎任何帮助。
更新:我已按如下方式更改了数据库的副本:
let directoryUrls = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
let applicationDocumentDirectory = directoryUrls[0]
let managedContext = coreDataStack.persistentContainer.viewContext
let storeUrl = applicationDocumentDirectory.appendingPathComponent("GuessGreek.sqlite")
print("AppDelegate", #function, "StoreURL", storeUrl)
if !FileManager.default.fileExists(atPath: (storeUrl.path)) {
print("Copying databases...")
let sourceSqliteURLs = [
Bundle.main.url(forResource: "GuessGreekDatabase", withExtension: "sqlite")!,
Bundle.main.url(forResource: "GuessGreekDatabase", withExtension: "sqlite-wal")!,
Bundle.main.url(forResource: "GuessGreekDatabase", withExtension: "sqlite-shm")!]
let destSqliteURLs = [
applicationDocumentDirectory.appendingPathComponent("GuessGreek.sqlite"),
applicationDocumentDirectory.appendingPathComponent("GuessGreek.sqlite-wal"),
applicationDocumentDirectory.appendingPathComponent("GuessGreek.sqlite-shm")]
for index in 0..<sourceSqliteURLs.count {
do {
try FileManager.default.copyItem(at: sourceSqliteURLs[index], to: destSqliteURLs[index])
print(#function, "Done copying")
} catch {
print(error)
}
do {
try managedContext.save()
} catch let error as NSError {
print("Error While Saving Data: \(error.userInfo)")
}
}
}
我从Sim中移除了应用程序并清理。当我运行时,我收到文件无法复制的错误,因为它已经存在...我在这里遗漏了一些东西。
答案 0 :(得分:1)
NSPersistentContainer
默认使用Application Support目录,而不是文档目录。
如果在loadPersistentStores完成块中打印出storeURL的值,您将看到它指向Application支持。发生的事情是,它正在根据您的模型创建一个空白数据库,忽略您所制作的副本。
要么复制到应用程序支持,要么传入NSPersistentStoreDescription
对象,其中URL指向文档目录,如果你想控制NSPersistentContainer
的作用。
值得注意的是这些界限:
let directoryUrls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let applicationDocumentDirectory = directoryUrls[0]
let storeUrl = applicationDocumentDirectory.appendingPathComponent("GuessGreek.sqlite")
在您当前的代码中完全没有做任何事情。
另外值得注意的是 - 您的SQLiteManager屏幕截图表明该文件名为GuessGreekDatabase.sqlite
,但您的NSPersistentContainer默认为商店名称GuessGreek.sqlite
,因此可能还需要修复,除非您在此期间执行此操作副本。