Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用SQLite(Swift)将数据库更改保存到.db文件中_Ios_Swift_Sqlite - Fatal编程技术网

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

Ios 使用SQLite(Swift)将数据库更改保存到.db文件中,ios,swift,sqlite,Ios,Swift,Sqlite,在我的项目中,我正在使用sqlite3\u open从.db打开一个已经存在的数据库。此文件是使用命令行工具sqlite3创建的。我正在更新表中的一些行,这很好,但这些更新只在数据库的临时实例中进行。我如何更新我的.db文件,以便将来运行项目时使用更新的数据 有人问如何在Swift中保存SQLite数据库。但这个答案似乎在某种程度上并不令人满意,因为该文件应该以sqlite3创建的格式编写,这样就可以通过sqlite3\u open再次打开它 是否有SQLite提供的函数?我找不到任何相关内容…

在我的项目中,我正在使用
sqlite3\u open
.db
打开一个已经存在的数据库。此文件是使用命令行工具
sqlite3
创建的。我正在更新表中的一些行,这很好,但这些更新只在数据库的临时实例中进行。我如何更新我的
.db
文件,以便将来运行项目时使用更新的数据

有人问如何在Swift中保存SQLite数据库。但这个答案似乎在某种程度上并不令人满意,因为该文件应该以
sqlite3
创建的格式编写,这样就可以通过
sqlite3\u open
再次打开它


是否有SQLite提供的函数?我找不到任何相关内容…

您无法修改捆绑包的内容。因此,您需要将该文件复制到某个目录中,以便对其进行修改。历史上,我们可能建议使用“文档”文件夹进行此操作。但是现在我们使用“应用程序支持目录”。看

无论如何,基本思想是:

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

  • 尝试打开应用程序支持目录中的数据库(使用
    SQLITE\u READWRITE
    选项,但不要使用
    SQLITE\u CREATE
    选项…如果找不到,我们不希望它创建空白数据库);及

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

因此,可能类似于:

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)
}

你所说的“临时实例”是什么意思?你不是在做所有应用程序都做的事情,即在第一次运行时将捆绑的数据库文件从资源捆绑包复制到Documents文件夹或其他适当的沙盒文件夹,然后在打开和使用数据库时使用该副本吗?我只是在Xcode中将数据库文件拖到我的项目中。我选择了“创建组”,并将其添加到目标。在编程上,我不做任何特殊的事情。我只是打开文件并更新一些行,如前所述。如果你在真实设备上运行,你的应用程序将无法工作,因为应用程序包是只读的。你的意思是不会?将数据库文件放在用户文档目录或类似目录中,然后从那里打开它。谢谢!这正是我需要的