XCode14.1中MacOS Swift App无法读取用户选择文件求助
问题背景
我开发了一款简单的MacOS Swift应用,通过NSOpenPanel实现用户选择文件并展示内容的功能。应用已开启沙箱,且配置了如下权限:
com.apple.security.files.user.-selected.read-write Boolean YES
选择文件的对话框代码:
func chooseFile() -> String? { let dialog = NSOpenPanel(); dialog.title = "Choose multiple files | Our Code World"; dialog.showsResizeIndicator = true; dialog.showsHiddenFiles = false; dialog.canChooseDirectories = false; dialog.allowsMultipleSelection = false; if (dialog.runModal() == NSApplication.ModalResponse.OK) { // 结果包含所有选中路径的数组 let results = dialog.urls if results.count > 0 { return results[0].path } } else { // 用户点击了“取消” return nil } return nil }
读取并展示文件内容的代码:
@IBAction func openFile(_ sender: Any) { if let strFilePath = myAppManager.chooseFile() { // 创建URL let fileURL = URL(string: strFilePath) // 解包可选值 if let fileURL = fileURL { // 读取文件 do { let strFileContents = try String(contentsOf: fileURL, encoding: .utf8) txtView.string = strFileContents } catch { print("读取文件错误: \(strFilePath)") } } else { print("从路径创建文件URL错误: \(strFilePath)") } } else { print("用户取消了文件选择。") } }
遇到的问题
测试rtf文件和Python(.py)文件均读取失败,报错信息:
2022-11-22 09:55:20.463374-0500 MarsTyper[8565:189921] NSURLConnection finished with error - code -1002 读取文件错误: /Users/xxxxxxxxxxxxxx/Desktop/test.rtf
额外吐槽:
@Apple - 错误信息只给错误码,文档里只列枚举,还得点击才能看对应含义,太麻烦了。
对应的错误枚举是:NSURLErrorNoPermissionsToReadFile = -1102 // 没有读取文件的权限
核心疑问
是否需要指定文件类型才能解决这个问题?
解决方案
1. 修复URL创建错误
你在openFile里用URL(string: strFilePath)创建本地文件URL是错误的,这个方法是用来生成网络URL的。本地文件路径必须用URL(fileURLWithPath: strFilePath),否则会生成无效URL,触发权限报错。
修改后的openFile代码:
@IBAction func openFile(_ sender: Any) { if let strFilePath = myAppManager.chooseFile() { // 正确创建本地文件URL let fileURL = URL(fileURLWithPath: strFilePath) do { let strFileContents = try String(contentsOf: fileURL, encoding: .utf8) txtView.string = strFileContents } catch { print("读取文件错误: \(strFilePath),详情: \(error)") } } else { print("用户取消了文件选择。") } }
2. 修复沙箱权限配置错误
你的权限键拼写有误:com.apple.security.files.user.-selected.read-write里多了一个不必要的点,正确的键应该是com.apple.security.files.user-selected.read-write。这个拼写错误会导致沙箱权限不生效,直接引发读取权限不足。
正确的沙箱权限配置:
<key>com.apple.security.files.user-selected.read-write</key> <true/>
3. 文件类型指定(可选)
不是必须,但如果想限制用户只能选择特定类型的文件,可以给NSOpenPanel添加类型过滤:
func chooseFile() -> String? { let dialog = NSOpenPanel(); dialog.title = "选择文件 | Our Code World"; dialog.showsResizeIndicator = true; dialog.showsHiddenFiles = false; dialog.canChooseDirectories = false; dialog.allowsMultipleSelection = false; // 添加允许的文件扩展名 dialog.allowedFileTypes = ["rtf", "py", "txt"] if dialog.runModal() == .OK { return dialog.urls.first?.path } return nil }
内容的提问来源于stack exchange,提问作者PruitIgoe
相关产品推荐
相关产品推荐

