sqlite3_open适用于Swift playground而非Swift应用程序

xjreopfe  于 2023-08-02  发布在  Swift
关注(0)|答案(1)|浏览(141)

当我在Swift Playground中运行以下代码时,它返回了成功。当我将它复制到我的Xcode项目时,它返回了失败。我想它与路径有关,所以我在谷歌上搜索并尝试了path.cString(使用:String.Encoding.utf8)但仍然没有运气。我不明白的是为什么它在操场上工作,但在应用程序本身却不行。

var db: OpaquePointer? = nil;
let path:String="/Users/williamstorey/Documents/db182.db"
if sqlite3_open(path ,&db) == SQLITE_OK {
   print("SUCCESS")
} else {
   print("FAILURE");
}

字符串

cotxawn7

cotxawn71#

最有可能的问题是你的应用是沙盒的,不能直接打开那里的文件。您可以动态构建URL,并且您将在沙箱中获得安全的文件URL/路径:

let fileURL = try! FileManager.default
    .url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
    .appendingPathComponent("db182.db")

字符串
请参见《文件系统编程指南》:库目录存储应用程序特定的文件。另请参阅关于应用沙盒。
如果你真的想打开沙箱之外的文件,你需要请求用户的权限(例如,使用NSOpenPanel,如Accessing files from the macOS App Sandbox中所讨论的)。
几点补充意见:
1.我将捕获任何sqlite3_xxx函数(如sqlite3_opensqlite3_open_v2)的返回代码,并使用它来诊断问题的根源。您可以使用这个返回代码来确定它不仅不是SQLITE_OK,而且更重要的是,您实际收到的返回代码是什么。
1.在出现错误的情况下,我还建议使用sqlite3_errmsg检索错误消息。在某些错误条件下(特别是当准备SQL语句时),这可以提供更多关于哪里出错的信息(尽管,无可否认,在这里,它不是那么有启发性)。但是它将错误转换为易于理解的内容(而不必通过error codes)。
1.如果sqlite3_open失败,请不要忘记sqlite3_close。我知道这看起来很奇怪,但无论成功与否,我们都必须关闭数据库,否则您将泄漏内存。正如documentation所说:
无论打开时是否发生错误,当不再需要database connection句柄时,都应该通过将其传递给sqlite3_close()来释放与database connection句柄关联的资源。
如果要存储该数据库连接,则可能还需要在sqlite3_close之后nil该不透明指针,以确保此属性更准确地反映数据库连接的状态。
因此,把这些放在一起,也许是沿着以下路线的东西:

var db: OpaquePointer?

func open(
    fileURL: URL,
    flags: Int32 = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE
) throws {
    let returnCode = sqlite3_open_v2(fileURL.path, &db, flags, nil)

    guard returnCode == SQLITE_OK else {
        let message = sqlite3_errmsg(db).flatMap { String(cString: $0) } ?? "Unknown error"
        print(#function, "error code:", returnCode, "error message:", message)
        close(db)
        throw …
    }
}

func close() {
    sqlite3_close(db)
    db = nil
}

相关问题