macOS 应用中,如果希望访问特定目录(如Downloads等文件夹),需要配合App Sandbox系统机制来允许用户授予访问权限。实现“下载”、“桌面”、“文稿”等目录的访问。
管理App Sandbox权限
打开Xcode项目,TARGETS – Signing & Capabilities,在Xcode16中,macOS项目默认添加App Sandbox权限。
如果没有App Sandbox权限,则在Capability中选择并添加 App Sandbox。

App Sandbox权限说明
1、Network(网络访问)
Incoming Connections (Server):允许 App 接受外部设备的连接,例如开 HTTP Server。默认关闭。
Outgoing Connections (Client):允许 App 主动连接网络,访问 Web API、下载文件等。默认开启(大多数 App 需要)。
2、Hardware(硬件访问)
Camera:访问摄像头(系统会弹窗提示用户)。
Audio Input:访问麦克风。
USB:访问连接的 USB 设备(较少使用)。
Printing(两项):打印权限(可能重复显示)。
Bluetooth:访问蓝牙设备(macOS 11+)。
3、App Data(用户隐私数据)
Contacts:访问通讯录(需弹窗授权)。
Location:获取定位信息(需 Info.plist 配置)。
Calendar:访问日历事件。
4、File Access(文件访问权限)
User Selected File:用户通过 NSOpenPanel 选取的文件/目录,可长期访问。
Downloads Folder:是否允许访问 ~/Downloads。
Pictures Folder:是否允许访问 ~/Pictures。
Music Folder:是否允许访问 ~/Music。
Movies Folder:是否允许访问 ~/Movies。
每个文件夹权限都可以设为:
None:禁止访问
Read Only:只读
Read/Write:读写(建议仅在需要写入时开启)
注意:这些权限如果不勾选,即使调用相关 API,系统也会拒绝访问或崩溃。其中部分权限属于 macOS 的 [TCC(Transparency Consent Control)系统],必须由用户授权才能访问。
实际应用
例如,将图片保存到Downloads文件夹中。
首先,在App Sandbox中开启Downloads权限:

图片保存文件夹的代码:
func saveTestImage() {
// 1. 创建一个空白 NSImage(假图像)
let size = NSSize(width: 200, height: 200)
let image = NSImage(size: size)
image.lockFocus()
NSColor.systemBlue.setFill()
NSBezierPath.fill(NSRect(origin: .zero, size: size))
image.unlockFocus()
// 2. 转换为 JPEG 格式的 Data
guard let tiffData = image.tiffRepresentation,
let bitmap = NSBitmapImageRep(data: tiffData),
let jpegData = bitmap.representation(using: .jpeg, properties: [.compressionFactor: 0.8]) else {
print("转换图片失败")
return
}
// 3. 拼接 Downloads 路径
let downloads = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!
let filename = "test-image-\(UUID().uuidString.prefix(6)).jpg"
let fileURL = downloads.appendingPathComponent(filename)
// 4. 写入文件
do {
try jpegData.write(to: fileURL)
print("成功保存图片到:\(fileURL.path)")
} catch {
print("保存失败:\(error)")
}
}
var body: some View {
VStack {
// 保存图片
Button("保存图片到Downloads文件夹") {
saveTestImage()
}
}
}
当点击按钮时,会创建图像并尝试保存到Downloads文件夹中。
如果没有开启App Sandbox的Downloads权限,Xcode会提示:
保存失败:Error Domain=NSCocoaErrorDomain Code=513 "你没有将文件“test-image-6A334C.jpg”存储到文件夹“下载”中的权限。" UserInfo={NSFilePath=/Users/fangjunyu/Library/Containers/com.fangjunyu.ImageSlim/Data/Downloads/test-image-6A334C.jpg, NSURL=file:///Users/fangjunyu/Library/Containers/com.fangjunyu.ImageSlim/Data/Downloads/test-image-6A334C.jpg, NSUnderlyingError=0x60000009de90 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
App 启动了:name = NSWorkspaceDidLaunchApplicationNotification, object = Optional(<NSWorkspace: 0x600000ccc0f0>), userInfo = Optional([AnyHashable("NSApplicationProcessSerialNumberHigh"): 0, AnyHashable("NSApplicationBundleIdentifier"): com.microsoft.VSCode, AnyHashable("NSApplicationProcessIdentifier"): 92797, AnyHashable("NSApplicationPath"): /Applications/Visual Studio Code.app, AnyHashable("NSApplicationProcessSerialNumberLow"): 116096689, AnyHashable("NSApplicationName"): Code, AnyHashable("NSWorkspaceApplicationKey"): <NSRunningApplication: 0x6000020d2880 (com.microsoft.VSCode - 92797) LSASN:{hi=0x0;lo=0x6eb7eb1}>])
表示图片保存失败。
如果开启App Sandbox,则会将400px * 400px的图片保存到Downloads文件夹中。

扩展知识
正确访问目录的方式
例如,我们需要访问下载目录的文件,我们可以不开启App Sandbox权限,而是通过用户主动授权的方式访问文件。
import AppKit
Button("选择下载目录") {
let panel = NSOpenPanel()
panel.canChooseDirectories = true
panel.canChooseFiles = false
panel.directoryURL = FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first
if panel.runModal() == .OK {
let selectedURL = panel.url!
NSWorkspace.shared.open(selectedURL) // 或者记录这个 URL
}
}
当点击Button后,系统弹出选择框,让用户选择打开的文件。

这也是Apple推荐的方式。
I very delighted to find this internet site on bing, just what I was searching for as well saved to fav