SwiftUI fileImporter获取URL:fileExists返回false但Data读取正常
问题原因解析
这是macOS/iOS沙盒安全机制导致的典型问题,核心逻辑在于安全作用域URL的特性:
安全作用域URL的路径不具备全局有效性:通过
.fileImporter获取的URL是带安全作用域标记的,它的path()返回的只是文件在系统中的物理路径字符串,但沙盒应用没有直接通过这个字符串访问文件的权限。FileManager.default.fileExists(atPath:)接收的是路径字符串,无法关联你之前通过startAccessingSecurityScopedResource()获取的临时权限,因此会判定文件不存在。直接操作URL才能利用安全作用域权限:
Data(contentsOf: url)和FileManager.default.contentsOfDirectory(at: url, ...)都是直接传入安全作用域URL,系统会自动识别并使用你已获取的临时权限,所以能正常读取文件内容或目录列表。
解决方案
如果需要判断文件是否存在,不要用路径字符串,直接基于URL操作:
// 方式1:结合isDirectory参数判断 func fileExists(at url: URL) -> Bool { guard url.startAccessingSecurityScopedResource() else { return false } defer { url.stopAccessingSecurityScopedResource() } var isDir: ObjCBool = false let exists = FileManager.default.fileExists(atPath: url.path(), isDirectory: &isDir) return exists && !isDir.boolValue } // 方式2:读取URL资源属性(更推荐) func fileExists(at url: URL) -> Bool { guard url.startAccessingSecurityScopedResource() else { return false } defer { url.stopAccessingSecurityScopedResource() } do { let resourceValue = try url.resourceValues(forKeys: [.isRegularFileKey]) return resourceValue.isRegularFile == true } catch { return false } }
注意:所有操作必须在startAccessingSecurityScopedResource()返回true的前提下执行,操作完成后务必调用stopAccessingSecurityScopedResource()释放权限。
内容的提问来源于stack exchange,提问作者Ky -
相关产品推荐
相关产品推荐

