将 SQLite 数据库附加到应用程序

Attaching SQLite database to an application

我的应用程序应该使用 SQLite 数据库,我想将其插入到应用程序中。 sqlite 文件直接位于应用程序文件夹中(您可以在屏幕截图中看到)。如果我在 let storeUrl = URL(fileURLWithPath:FileManager.default.currentDirectoryPath).appendingPathComponent("/Users/nm/App/Songbook/Model.sqlite") 行中添加完整路径,则应用程序将从数据库中读取数据。但是如果我只键入 Model.sqlite,应用程序不会读取。我不能在应用程序的最终版本中这样保留它。请建议我做错了什么。以下是完整代码。

struct PersistenceController {
    static let shared = PersistenceController()
    let container: NSPersistentContainer
    
    init() {
        container = NSPersistentContainer(name: "Model")
        let storeUrl = URL(fileURLWithPath: FileManager.default.currentDirectoryPath).appendingPathComponent("/Users/nm/App/Spiewnik/Spiewnik/Model.sqlite")
        
        container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: storeUrl)]
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
    }

enter image description here

更新数据: 我的代码现在看起来像这样,在模拟器中一切正常。但是,在 phone 上,数据库是空的。

    static let shared = PersistenceController()
    let container: NSPersistentContainer
    
    init() {
        container = NSPersistentContainer(name: "Model")
        let dbName = "Model.sqlite"
        let dbUrl = getDocumentsDirectory().appendingPathComponent(dbName)
        if !FileManager.default.fileExists(atPath: dbUrl.path) {
            //move the file
            do {
                if let fileURL = Bundle.main.url(forResource: "Model", withExtension: "sqlite"){
                    try FileManager.default.copyItem(at: fileURL, to: dbUrl)
                }
            } catch {
                print(error)
                fatalError(error.localizedDescription)
            }
        }
        container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: dbUrl)]
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
    }
    func getDocumentsDirectory() -> URL {
        let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) //or .libraryDirectory
        let documentsDirectory = paths[0]
        return documentsDirectory
    }

您似乎正在尝试从应用程序的捆绑包中加载数据库,这会出现问题,因为捆绑包文件不可写。相反,您需要将其复制到您可以 read/write 访问的位置。一种可能是应用程序的文档目录(或库目录,这在 macOS 上很常见)。

首先,您需要能够获得该目录的 URL:

func getDocumentsDirectory() -> URL {
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) //or .libraryDirectory
    let documentsDirectory = paths[0]
    return documentsDirectory
}

然后,检查数据库是否已经存在。如果没有,请复制您的捆绑文件:

let dbName = "Model.sqlite"
let dbUrl = getDocumentsDirectory().appendingPathComponent(dbName)
if !FileManager.default.fileExists(atPath: dbUrl.path) {
    //move the file
    do {
        try FileManager.default.copyItem(at: Bundle.main.url(forResource: "Model", withExtension: "sqlite")!, to: dbUrl)
    } catch {
        print(error)
        fatalError(error.localizedDescription)
    }
}

//load your database from dbUrl here

然后,您可以使用 dbUrl 并从您现在复制的文件加载数据库。