sqlite3_open在Swift Playground中有效,但在Swift应用程序中无效。

4
当我在Swift Playground中运行以下代码时,它返回了成功。但是,当我将它复制到我的Xcode项目中时,它返回了失败。我猜这与路径有关,所以我Google了一下,尝试了path.cString(using: String.Encoding.utf8),但仍然没有成功。我不明白的是为什么在Playground中可以工作,但在应用程序本身中却不行。
var db: OpaquePointer? = nil;
let path:String="/Users/williamstorey/Documents/db182.db"
if sqlite3_open(path ,&db) == SQLITE_OK {
   print("SUCCESS")
} else {
   print("FAILURE");
}

你不能随便打开任何文件。 - El Tomato
您可以使用 NSOpenPanel 来有效地请求权限。 - Rob
顺便提一下,在Swift中不需要上面的分号。 - Rob
1个回答

4

你不应该只检查它是否为SQLITE_OK,而应该保存返回代码并检查返回的值,如果它不是SQLITE_OK。 如果您不查看实际的返回代码值,那么您只是在猜测问题可能出在哪里。

但最有可能的问题是您的应用程序被沙盒化,无法在其中打开文件。 您应该动态构建URL,然后您将获得安全的文件URL /路径:

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

print(fileURL.path)

let returnCode = sqlite3_open(fileURL.path, &db)

这将导致类似以下的结果:
/Users/williamstorey/Library/Containers/com.domain.MyApp/Data/Documents/db182.db

坦白说,您可能希望使用 .applicationSupportDirectory 而不是 .documentDirectory。请参阅 文件系统编程指南:库目录存储特定于应用程序的文件。另请参阅 有关 App Sandbox 的信息

很抱歉,我确实检查了返回结果,它是14 SQL_CANTOPEN。我完全忘记提到这一点了。 - eleethesontai
是的,如果您在没有请求用户权限的沙盒环境中尝试打开文件,则会收到“SQLITE_CANTOPEN”错误。因此,要么像上面所示构建文件URL /路径,要么如果您必须在问题中使用该URL的文件,则必须请求用户权限才能这样做。 - Rob
这是结果。/Users/williamstorey/Library/Containers/c4g.db182-osx/Data/Documents/db182.db 那不是文件所在的地方吗?对不起,URL和沙盒范例对我来说很新。 - eleethesontai
1
是的,一旦使用fileURL.path创建数据库,它显然就会结束在那里。沙盒是iOS/macOS编程中的一个范例,使我们远离应用程序可以随意访问文件系统中的文件的世界,而是将它们限制在特定的应用程序专用文件夹集合中。当运行正确沙盒化的应用程序时,您可以更加自信地确保它不会访问/操作不应该访问的数据。作为开发人员,这有点烦人,但作为最终用户,这很棒,因为它使我们的机器更安全。 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接