[英]swift3 CoreData fetch returns nil
請參閱下面的更新:
有許多與此類似的問題,但似乎沒有一個足夠的答案可以回答我,因此將不勝感激。
我有一個在另一個應用程序中創建的預加載數據庫。 如果是第一次運行,則將數據庫復制到documents目錄中。 從日志中可以看到數據庫位於預期位置:
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)")
}
}
我的應用程序委托外有一個核心數據堆棧,如下所示:
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中刪除了該應用,然后進行了清理。 運行時,出現錯誤,因為該文件已存在,因此無法復制...我在這里丟失了一些東西。
NSPersistentContainer
使用應用程序支持目錄,而不是文檔目錄。
如果在loadPersistentStores完成塊中打印出storeURL的值,您將看到它指向應用程序支持。 發生的事情是它正在基於您的模型創建一個空白數據庫,而忽略了您已創建的副本。
而是復制到應用程序支持中,或者如果要控制NSPersistentContainer
在哪里NSPersistentContainer
操作,請傳入一個帶有指向文檔目錄的URL的NSPersistentStoreDescription
對象。
值得注意的是這些行:
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
,所以可能還需要修復,除非你正在做的復制過程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.