3

我正在尝试写入我创建的报价数据库。如果用户选择“收藏”按钮,它将在 SQLITE 数据库的收藏列中添加一个 1(或真)值。由于某种原因,我无法写入数据库,当我执行此代码时:

    @IBAction func addFavorite(_ sender: Any) {
        var configuration = Configuration()
        configuration.readonly = false
        let dbPath = Bundle.main.path(forResource: "data", ofType: "db")!
        let dbQueue = try! DatabaseQueue(path: dbPath, configuration: configuration)

        try! dbQueue.inDatabase { db in
            try db.execute("""
UPDATE quotes SET favorite = 1 WHERE quote = ?;
""",
                                           arguments: [quoteLabel.text])
    }

我希望结果写入数据库并将 1 放在最喜欢的列中,但遗憾的是事实并非如此。我收到此错误:

线程 1:致命错误:“尝试!” 表达式意外引发错误:SQLite error 8 with statement UPDATE quotes SET favorite = 1 WHERE quote = ?arguments ["Abstinence is the greatstrengthener and clearer of reason."]: 尝试编写只读数据库

我试过chmod 755数据库,但也没有用。我错过了什么吗?

4

1 回答 1

5

数据库的路径是应用程序资源的路径。应用资源不能在 iOS 中修改。

有关详细信息,请参阅文件系统基础知识。特别相关的报价:

[...] 应用程序包。此目录包含应用程序及其所有资源。

您无法写入此目录。为防止篡改,捆绑目录在安装时进行签名。写入此目录会更改签名并阻止您的应用程序启动。但是,您可以获得对存储在应用程序包中的任何资源的只读访问权限。有关详细信息,请参阅资源编程指南

现在,如果无法修改,您如何在数据库中写入?

好吧,你把它复制到你可以修改的地方。您永远不会修改捆绑的数据库资源,而只会修改副本。

再次有可用的文档:如何打开存储为应用程序资源的数据库?GRDB 常见问题解答 说:

如果应用程序要修改数据库资源,您需要将其复制到可以修改的地方。例如,在应用程序支持目录中。只有这样,打开一个连接:

let fileManager = FileManager.default

let dbPath = try fileManager
    .url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
    .appendingPathComponent("db.sqlite")
    .path

if !fileManager.fileExists(atPath: dbPath) {
    let dbResourcePath = Bundle.main.path(forResource: "db", ofType: "sqlite")!
    try fileManager.copyItem(atPath: dbResourcePath, toPath: dbPath)
}

let dbQueue = try DatabaseQueue(path: dbPath)
于 2017-12-11T16:22:39.193 回答