簡體   English   中英

swift3 CoreData提取返回nil

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM