macOS沙盒应用唯一可持久写入的私有空间是~/Library/Containers/<bundle-id>/Data/,备份恢复必须限于该路径内,依赖security-scoped bookmarks和钥匙串管理授权与密钥,恢复时需重建访问凭证并校验书签有效性。

macOS 沙盒应用的数据容器(~/Library/Containers/<bundle-id>/Data/)是其唯一默认可持久写入的私有空间,备份与恢复必须围绕该路径展开,不能依赖系统级工具(如 Time Machine 全盘备份)自动覆盖沙盒边界,否则重启后访问失效或数据丢失。
沙盒容器数据的可备份范围
沙盒内天然可读写的路径明确且有限:
-
主容器目录:
~/Library/Containers/<bundle-id>/Data/,含Documents、Caches、Preferences、Application Support等子目录 -
临时目录:
~/Library/Containers/<bundle-id>/Data/tmp/(不持久,重启清空,不建议用于备份源) -
用户显式授权路径:通过
NSOpenPanel选择的文件夹,配合 security-scoped bookmarks 持久化后,其书签数据可存于容器内,但原始路径本身不属于容器,不可直接打包备份
安全可靠的本地备份操作方式
备份动作必须在沙盒内完成,目标也须位于沙盒容器中(如 Application Support/Backup),避免越权写入失败:
- 使用
FileManager.default.copyItem(at:to:)或FileManager.default.createArchive(at:...)将Data/Documents和Data/Application Support打包为 .zip 或 .tar.gz,存入Data/Application Support/Backup/ - 备份前检查磁盘空间:
URL(fileURLWithPath: NSHomeDirectory()).resourceValues(forKeysRequested: [.volumeAvailableCapacityForImportantUsageKey]) - 若需加密,使用
SecKeyGeneratePair或CryptoKit在沙盒内完成,密钥不得硬编码,应由用户密码派生并缓存在钥匙串(Keychain,需声明com.apple.security.keychain-access-groups权限)
恢复流程必须重走权限初始化
恢复不是简单解压——尤其涉及用户授权路径时,需重建访问凭证:
- 从容器内备份包解压到对应子目录(如
Data/Documents)后,若原数据含 security-scoped bookmarks,需调用URL.resolvingBookmarkData(_:)尝试恢复 URL - 对每个恢复出的 bookmark URL,必须调用
startAccessingSecurityScopedResource()并检查返回值;若isStale == true,需引导用户重新通过NSOpenPanel授权 - 偏好设置(
UserDefaults)恢复需调用UserDefaults(suiteName:)并确保App Group已在 entitlements 中启用(com.apple.security.application-groups),否则跨进程同步失败
注意事项与常见断点
以下行为会导致备份无效或恢复失败:
- 将 bookmarkData 直接存到
~/Desktop或/tmp—— 沙盒外路径无法写入,会静默失败或抛出Operation not permitted - 备份时未包含
Application Support下的书签数据或钥匙串项,导致恢复后无法访问用户授权的外部文件夹 - Info.plist 缺少
NSDocumentsFolderUsageDescription等描述键,首次请求访问时弹窗被系统拦截,用户无提示 - 未在 Xcode Capabilities 中启用
App Sandbox Bookmarks,即使代码调用bookmarkData也会返回 nil


















