ios - 使用 SQLite (Swift) 将数据库更改保存到 .db 文件中

标签 ios swift sqlite

在我的项目中,我正在从.db打开一个已经存在的数据库。与 sqlite3_open 。该文件是使用命令行工具 sqlite3 创建的。我正在更新表中的一些行,效果很好,但这些更新仅在数据库的临时实例中进行。我怎样才能更新我的.db文件以便我的项目将来运行时使用更新的数据?

有人问here如何在 Swift 中保存 SQLite 数据库。但在我看来,答案似乎不太令人满意,因为该文件应该以与 sqlite3 创建的格式相同的格式编写。 ,这样就可以通过 sqlite3_open 再次打开它.

是否有 SQLite 提供的函数?我找不到任何东西......

最佳答案

您无法修改 bundle 的内容。因此,您需要将文件复制到可以修改的目录中。从历史上看,我们可能建议为此使用“文档”文件夹。但现在我们使用“应用程序支持目录”。请参阅iOS Storage Best Practices .

无论如何,基本思想是:

  • 将原始数据库包含在 bundle 中(如果尚未将其添加到应用程序的目标中);

    enter image description here

  • 尝试打开数据库(使用SQLITE_READWRITE选项,但不使用SQLITE_CREATE选项...如果不这样做,我们不希望它创建一个空白数据库没有找到)在应用程序支持目录中;和

  • 如果失败(因为找不到文件),请将数据库从 bundle 复制到应用程序支持目录,然后重试

因此,也许是这样的:

var db: OpaquePointer?

enum DatabaseError: Error {
    case bundleDatabaseNotFound
    case sqliteError(Int32, String?)
}

func openDatabase() throws {
    let fileURL = try FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        .appendingPathComponent("database.db")

    // try opening database and just return if it succeeded

    if sqlite3_open_v2(fileURL.path, &db, SQLITE_OPEN_READWRITE, nil) == SQLITE_OK {
        return
    }

    // if it failed, clean up before trying again ...

    sqlite3_close(db)
    db = nil

    // then copy database from bundle ...

    guard let bundlePath = Bundle.main.url(forResource: "database", withExtension: "db") else {
        throw DatabaseError.bundleDatabaseNotFound
    }
    try FileManager.default.copyItem(at: bundlePath, to: fileURL)

    // and try again

    let rc = sqlite3_open_v2(fileURL.path, &db, SQLITE_OPEN_READWRITE, nil)

    if rc == SQLITE_OK { return }

    // and if it still failed, again, clean up, and then throw error

    let errorMessage = sqlite3_errmsg(db)
        .flatMap { String(cString: $0) }

    sqlite3_close(db)
    db = nil

    throw DatabaseError.sqliteError(rc, errorMessage)
}

关于ios - 使用 SQLite (Swift) 将数据库更改保存到 .db 文件中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56416832/

相关文章:

ios - 解析 PFAnalytics 不跟踪推送打开

android - 在适配器类中保存 ImageButton 状态

ios - 在没有 Storyboard的情况下以编程方式添加容器 View ?

ios - viewDidAppear 适用于 iOS 8.1 及更高版本

iphone - 是否可以在 iOS5 中使用 Twitter API 发布照片?

ios - 用于验证图片下载的 HTTP 响应头内容长度

swift - 如何修复此代码上的 "Cannot convert value of type ' (CGFloat) -> Data ?' to expected argument type ' Data'"错误?

ios - UICollectionView 是否随着 Xcode 7、swift 2.0 更改了协议(protocol)?

perl - 异常 : Please criticize my code 后重试操作

ios - Xcode Sqlite update 语句只工作一次