Swift GRDB 写入数据库错误 "attempt to write a readonly database"

标签 swift database sqlite grdb

我正在尝试写入我创建的报价数据库。如果用户选择“收藏夹”按钮,它将在 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,但遗憾的是情况并非如此。我收到此错误:

Thread 1: Fatal error: 'try!' expression unexpectedly raised an error: SQLite error 8 with statement UPDATE quotes SET favorite = 1 WHERE quote = ? arguments ["Abstinence is the great strengthener and clearer of reason."]: attempt to write a readonly database

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

最佳答案

数据库的路径就是应用程序资源的路径。 iOS 无法修改应用资源。

参见 File System Basics了解更多信息。特别相关的引用:

[...] the app’s bundle. This directory contains the app and all of its resources.

You cannot write to this directory. To prevent tampering, the bundle directory is signed at installation time. Writing to this directory changes the signature and prevents your app from launching. You can, however, gain read-only access to any resources stored in the apps bundle. For more information, see the Resource Programming Guide.

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

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

再次有可用文档:How do I open a database stored as a resource of my application? GRDB 常见问题解答说:

If the application should modify the database resource, you need to copy it to a place where it can be modified. For example, in the Application Support directory. Only then, open a connection:

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)

关于Swift GRDB 写入数据库错误 "attempt to write a readonly database",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47734451/

相关文章:

ios - 如何向此 UITableView 添加额外的列并填充已获取的数据?

ios - 如何从滤镜中获取原始图像

java - 关于 SQL 目录的问题 - 它们到底是什么?

MySQL - 使用 LIMIT 有效地将两个 select 语句组合成一个结果

reactjs - Sequelize Op.like 和 Op.or 失败

php - 仅当 SQLite 表不存在时才创建它

ios - viewDidLoad 中带有参数的 SWIFT 函数

swift - 为什么允许 CountableRange 具有相同的 lowerBound 和 upperBound?

database - 无法在xcode中打开sqlite数据库

Android:使用 SD 卡上的 SQLite 数据库(根本不使用内部 Android 数据存储)