You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 19:24:03