macOS应用沙盒由内核强制执行,默认仅允许读写自身容器目录(~/Library/Containers/<bundle-id>/Data/)和tmp目录,以及用户通过NSOpenPanel显式授权的文件或文件夹;需配合security-scoped bookmarks持久化访问、正确配置Info.plist权限键值,并严格管理start/stop访问配对,否则重启后触发Operation not permitted错误。

macOS 应用沙盒(App Sandbox)不是“加个开关就能用”的功能,而是整套运行时约束体系——它不靠开发者自觉,而由内核强制执行。启用沙盒后,应用默认只能读写自己容器内的文件,其他任何路径(包括 ~/Documents、~/Desktop、/Applications)都会被系统拦截并返回 Operation not permitted。
沙盒能访问哪些位置?
沙盒应用天然拥有读写权限的路径只有:
- 自身容器目录:
~/Library/Containers/<bundle-id>/Data/(含 Documents、Caches、Preferences 等子目录) - 临时目录:
~/Library/Containers/<bundle-id>/Data/tmp/ - 用户通过 NSOpenPanel 或 NSSavePanel 显式选择的单个文件或文件夹(需配合安全书签才能复用)
- 经声明并获授权的系统资源,如照片库(Photos.framework)、通讯录、日历、麦克风、摄像头等
如何合法访问用户文件夹?
不能硬编码 ~/Documents 去 open() 或 write(),必须走用户授权+凭证管理流程:
- 用
NSOpenPanel弹出系统对话框,设置canChooseDirectories = true,让用户手动选中目标文件夹 - 调用
url.startAccessingSecurityScopedResource()开启本次访问权限 - 完成读写后,立即调用
url.stopAccessingSecurityScopedResource() - 若需重启后仍可访问,调用
url.bookmarkData(options: .withSecurityScope)生成书签数据,并存入自身容器(如 Application Support 目录) - 下次启动时,用
URL.resolvingBookmarkData(_:)恢复 URL,并再次startAccessing
权限配置与常见陷阱
仅写代码不够,Xcode 中必须同步完成三项配置:
- 在 Signing & Capabilities 中开启 App Sandbox,Xcode 自动写入
com.apple.security.app-sandboxentitlement - 勾选 User Selected File Access,生成
com.apple.security.files.user-selected.read-write权限(对应 Info.plist 中的键值) - 若使用书签持久化,还需启用 App Sandbox Bookmarks,添加
com.apple.security.files.bookmarks.app-scope
常见失败原因:忘记 start/stop 配对、把 bookmarkData 存到非沙盒路径、未处理 isStale 返回值、Info.plist 缺少对应 usage description(如访问照片库需 NSPhotoLibraryUsageDescription)。
调试与验证方法
运行应用后,打开活动监视器(Activity Monitor),菜单栏选择 View → Columns → Sandbox,确认你的进程对应列为 Yes。也可用命令行检查实际生效的 entitlements:
codesign -dv --entitlements :- /Applications/YourApp.app控制台(Console.app)中搜索 “sandboxd” 或 “deny file-read-data”,能直接看到被拦截的具体路径和系统拒绝原因。


















