macOS Big Sur下读取用户选定目录文件报权限错误如何解决
问题原因
macOS沙盒机制要求,所有通过安全作用域书签获取的目录/文件路径,必须先开启安全作用域访问权限,才能执行读取、遍历等操作。你之前保存文件时用的accessSecurityScopedResource(at:)是针对单个子文件的权限申请,遍历目录需要先给父目录本身申请权限。
修正方案
方案1:使用系统原生API配对开启/关闭权限
func loadFiles() { do { let directoryURL = try resolveURL(for: "savedDirectory") // 先开启目录的安全作用域访问 guard directoryURL.startAccessingSecurityScopedResource() else { throw NSError(domain: "com.yourapp.error", code: -1, userInfo: [NSLocalizedDescriptionKey: "无法获取目录访问权限"]) } // defer保证退出作用域时一定关闭权限,避免权限泄漏 defer { directoryURL.stopAccessingSecurityScopedResource() } let contents = try FileManager.default.contentsOfDirectory(at: directoryURL, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles]) for file in contents { print(file.absoluteString) // 父目录开启安全作用域后,子文件可直接读取,不需要重复申请权限 let fileContent = try String(contentsOf: file, encoding: .utf8) // 在此处将内容添加到你的数据struct即可 } } catch let error as ResolveError { print("Resolve error:", error) return } catch { print(error) return } }
方案2:复用自定义的accessSecurityScopedResource扩展
如果你的扩展支持直接作用在目录本身,直接把目录操作放到闭包内即可:
func loadFiles() { do { let directoryURL = try resolveURL(for: "savedDirectory") try directoryURL.accessSecurityScopedResource(at: directoryURL) { url in let contents = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: [.skipsHiddenFiles]) for file in contents { print(file.absoluteString) let fileContent = try String(contentsOf: file, encoding: .utf8) // 处理文件内容 } } } catch let error as ResolveError { print("Resolve error:", error) return } catch { print(error) return } }
注意事项
- 必须保证
Info.plist中已经开启对应的沙盒权限:com.apple.security.files.user-selected.read-write设为YES - 权限开启后只能在配对的作用域内执行文件操作,退出作用域前必须调用停止访问的方法,避免后续访问出现异常
内容的提问来源于stack exchange,提问作者Aleph
相关产品推荐
相关产品推荐

