Swift macOS应用重命名本地磁盘文件出现Permissions error如何解决?
问题原因
这个报错是macOS App Sandbox的权限限制导致的:默认开启沙盒的应用,仅能访问用户通过系统文件选择面板明确授权的路径,你当前的操作一方面是沙盒权限配置不全,另一方面是代码中转路径字符串的操作丢失了用户授权的安全访问标签,导致沙盒判定你没有对应目录的操作权限。
解决步骤
1. 配置Sandbox读写权限
打开Xcode项目,进入对应Target的「Signing & Capabilities」标签页,找到App Sandbox配置项,在File Access分类下做如下设置:
- 将User Selected File权限设置为 Read/Write
- 如果你需要操作外接磁盘(你的报错路径在/Volumes下属于外接存储),额外勾选「Removable Volumes」的读写权限即可
如果你开发的应用不需要上架App Store,也可以直接关闭App Sandbox开关,跳过沙盒限制。
2. 修正代码权限丢失问题
你当前将用户选择的URL转为字符串拼接路径的操作,会丢失系统授予的安全访问权限,应该全程使用URLAPI处理路径,同时主动开启安全访问作用域,修正后的参考代码如下:
let openPanel = NSOpenPanel() openPanel.canChooseDirectories = true openPanel.canChooseFiles = false openPanel.canCreateDirectories = false openPanel.allowsMultipleSelection = false if openPanel.runModal() == NSApplication.ModalResponse.OK, let mtsVideosFolder = openPanel.urls.first { // 开启安全访问作用域 let hasAccess = mtsVideosFolder.startAccessingSecurityScopedResource() defer { // 用完关闭安全访问 if hasAccess { mtsVideosFolder.stopAccessingSecurityScopedResource() } } let fileManager = FileManager.default guard let enumerator = fileManager.enumerator(at: mtsVideosFolder, includingPropertiesForKeys: [.contentModificationDateKey], options: .skipsHiddenFiles) else { return } let dateFormatter = DateFormatter() dateFormatter.timeZone = .current dateFormatter.dateFormat = "yyyy.MM.dd HH.mm.ss" for case let fileURL as URL in enumerator { guard fileURL.pathExtension.lowercased() == "mts" else { continue } do { // 直接从URL属性拿修改日期,不用单独写方法取 let fileAttrs = try FileManager.default.attributesOfItem(atPath: fileURL.path) guard let modDate = fileAttrs[.modificationDate] as? Date else { continue } let dateString = dateFormatter.string(from: modDate) // 用URL拼接目标路径,保留安全权限 let targetURL = mtsVideosFolder.appendingPathComponent("\(dateString).mts") // 避免重名覆盖,重名自动加序号后缀 var finalTargetURL = targetURL var suffix = 1 while fileManager.fileExists(atPath: finalTargetURL.path) { finalTargetURL = mtsVideosFolder.appendingPathComponent("\(dateString)_\(suffix).mts") suffix += 1 } try fileManager.moveItem(at: fileURL, to: finalTargetURL) print("Rename \(fileURL.path) to \(finalTargetURL.path)") } catch { print("处理文件\(fileURL.path)失败:\(error)") } } }
可选补充设置
如果你的应用需要经常操作固定目录不想每次都让用户选,可以在系统「安全性与隐私」设置里给你的应用开启「全磁盘访问」权限,也可以直接解决权限问题。
内容的提问来源于stack exchange,提问作者LilMoke
相关产品推荐
相关产品推荐

