Sandbox — 是 iOS 应用程序的隔离执行环境,限制对文件系统、网络、硬件资源和其他应用程序数据的访问。每个应用程序在安装时都会获得自己的沙盒环境,其所有文件操作都会自动重定向到此隔离区域。根据 Apple App Sandbox Design Guide (2026),沙盒架构基于三个保护级别:文件系统隔离、进程间通信控制以及通过权限(entitlements)显式请求许可的硬件资源分配。
要点
Sandbox — 是一种强制访问控制系统(Mandatory Access Control),在 iOS 内核层面(XNU — kernel extension Sandbox.kext)实现。每个应用程序在启动时都会获得一个唯一的 UUID 沙盒配置文件,该文件确定允许访问哪些系统资源。
沙盒架构包括三个关键组件:File System Isolation(每个应用程序只能看到自己的容器),Network Access Control(对本地网络的请求可能会受到限制)和 Inter-Process Communication(禁止与其他应用程序直接进行 IPC)。苹果在 iOS 2.0 中引入了沙盒,此后在每个主要版本中都显著加强了限制。
沙盒不是可选的 — 所有来自 App Store 的应用程序都在沙盒中运行。开发者无法禁用沙盒或绕过其限制。尝试访问被禁止的资源会以 EPERM 代码(Operation not permitted)错误结束,并记录到系统日志中。
import Foundation
// 尝试访问其他应用程序文件 — 返回 nil
let otherAppPath = "/var/mobile/Containers/Data/Application/OTHER-UUID/Documents/file.txt"
let data = try? Data(contentsOf: URL(fileURLWithPath: otherAppPath))
// data == nil — 沙盒阻止访问
// 正确访问 — 在自己的沙盒内
let fileManager = FileManager.default
guard let documentsURL = fileManager.urls(
for: .documentDirectory,
in: .userDomainMask
).first else { return }
let myFileURL = documentsURL.appendingPathComponent("notes.txt")
try "Hello, Sandbox!".write(to: myFileURL, atomically: true, encoding: .utf8)
iOS 上每个应用程序的沙盒包含几个预定义的目录,可通过 Foundation API 访问。在物理介质上的位置 — /var/mobile/Containers/Data/Application/{UUID}/,但开发者不应直接使用此路径:它在每次设备重启时都会更改,并且在不同的 iOS 版本中有所不同。
沙盒的主要目录:Bundle(.app — 只读,包含可执行代码和资源),Documents(用户数据,备份到 iCloud),Library(Caches、Preferences、Application Support — 具有不同的备份规则),tmp(临时文件,空间不足时由系统删除)。每个目录都有自己的生命周期和存储策略。
可以通过 NSHomeDirectory() 或 FileManager.url(for: .documentDirectory) 获取沙盒的物理路径。苹果建议使用基于 URL 的 API,因为它抽象了文件系统的内部结构,并且在 macOS 桌面版沙盒发生变化时保持稳定。
| 沙盒目录 | 通过 FileManager 获取 | 权限 |
|---|---|---|
| Documents | .documentDirectory | 读写 |
| Bundle | Bundle.main.bundlePath | 只读 |
| Library | .libraryDirectory | 读写 |
| tmp | NSTemporaryDirectory() | 读写 |
| App Group | .containerURL(forSecurityApplicationGroupIdentifier:) | 读写 |
直接访问 iOS 中其他应用程序的文件系统被完全阻止。即使开发者知道其他应用程序容器的 UUID,内核级别的沙盒在尝试读取或写入时会返回错误。这是 iOS 和 macOS 之间的根本区别,macOS 中的沙盒更加灵活。
苹果提供三种合法的应用程序间数据交换机制:UIDocumentPickerViewController(用户通过系统界面选择文件,应用程序获得 Security-Scoped URL),Share Extension(用于将数据传输到其他应用程序的扩展)和 App Groups(同一开发者的应用程序的共享目录)。
UIDocumentPicker — 无需预先配置即可访问其他应用程序文件的唯一方式。用户通过标准系统选择器显式选择文件,iOS 向应用程序提供临时的 Security-Scoped URL。访问权限在选择器关闭或调用 stopAccessingSecurityScopedResource 之前有效。
Security-Scoped Bookmark — 是一种 iOS 机制,允许在应用程序启动之间保持对沙盒外文件的访问。当用户通过 UIDocumentPicker 选择文件时,应用程序可以从 Security-Scoped URL 创建书签(bookmark)并将其保存在 UserDefaults 或其他存储中。
在下次启动时,应用程序通过 URLByResolvingBookmarkData 恢复访问,该函数返回 Security-Scoped URL。然后需要在读取文件前调用 startAccessingSecurityScopedResource,在完成工作后调用 stopAccessingSecurityScopedResource。调用平衡是强制性的 — 每个 start 必须有相应的 stop,否则系统将耗尽 Security-Scoped 资源限制。
// 创建 Security-Scoped Bookmark
func createBookmark(for url: URL) -> Data? {
return try? url.bookmarkData(
options: .minimalBookmark,
includingResourceValuesForKeys: nil,
relativeTo: nil
)
}
// 将书签数据解析为 URL
func resolveBookmark(data: Data) -> URL? {
var isStale = false
let url = try? URL.byResolvingBookmarkData(
data,
options: .withoutUI,
relativeTo: nil,
bookmarkDataIsStale: &isStale
)
if isStale {
// 书签已过期,需要创建新的
}
return url
}
重要限制:Security-Scoped Bookmarks 不适用于自己沙盒内的文件 — 仅适用于通过 UIDocumentPicker 或 iCloud Drive 获取的文件。书签包含 Security-Scoped 数据,允许系统识别哪个应用程序以及为哪个文件请求访问。如果应用程序证书过期或更改,书签将失效。
App Groups — 是一种 iOS 机制,允许同一开发者的多个应用程序(及其扩展)拥有共享的沙盒目录。要启用,需要在 Xcode 中添加 Capability App Groups 并为所有目标应用程序指定相同的组标识符。
共享的 App Groups 目录位于每个单独应用程序的沙盒之外,但组中的所有应用程序对其拥有完全读写访问权限。这允许在主应用程序、Today Widget、Watch Extension 和 Share Extension 之间交换文件、数据库(使用 App Group 中 Store URL 的 Core Data)和 UserDefaults(通过 initWithSuiteName)。
苹果建议使用 App Groups 在应用程序及其扩展之间同步状态。例如,Today Widget 可以从共享的 App Group 目录读取数据,主应用程序将最新数据写入该目录。然而,每个应用程序仍然与其他 App Groups 隔离 — 只有具有相同组标识符的应用程序才能访问。
iOS 中的沙盒施加了一系列严格的限制,在开发时必须考虑。主要限制包括:禁止动态代码(在沙盒外加载和执行代码),禁止未经用户许可直接访问通讯录、日历和照片(Privacy framework),以及限制创建子进程(fork、exec 被禁止)。
网络:应用程序可以通过 TCP/UDP 连接到任何远程服务器,但对 localhost 的访问受到限制 — 其他应用程序无法连接到您的应用程序内的服务器(调试构建除外)。App Store 应用程序的 multicast 和 broadcast UDP 也被阻止。
硬件资源:访问相机、麦克风、地理位置、蓝牙和 HealthKit 需要通过系统对话框获得用户的显式许可。对于每种资源类型,iOS 使用单独的 entitlement 和带有原因描述的 Info.plist 键(NSPhotoLibraryUsageDescription、NSCameraUsageDescription)。在 Info.plist 中没有原因描述的情况下请求权限会导致应用程序终止。
常见问题
Sandbox — 是 iOS 应用程序的隔离执行环境,限制对文件系统、网络和其他应用程序数据的访问。每个应用程序都有唯一的沙盒容器,其访问权限由 iOS 内核通过 Sandbox.kext 控制。
应用程序可以访问:Documents(用户数据)、Library(Caches、Preferences、Application Support)、tmp(临时文件)和 Bundle(只读)。App Group 目录对同一开发者组的应用程序可用。
通过 UIDocumentPickerViewController — 用户通过系统界面选择文件。iOS 提供 Security-Scoped URL,在调用 stopAccessingSecurityScopedResource 之前可访问。替代方案 — 使用 Share Extension 在应用程序之间传输数据。
Security-Scoped Bookmark — 是在应用程序启动之间保持对沙盒外文件访问的数据。从 UIDocumentPicker 获得的 Security-Scoped URL 通过 bookmarkData 创建。在下次启动时,书签通过 URLByResolvingBookmarkData 恢复。
不能,沙盒无法禁用对于来自 App Store 的应用程序。在越狱设备上可以禁用,但这与在 App Store 上发布不兼容。开发者可以在模拟器上无沙盒测试,但真实设备始终应用沙盒。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。