iOS 打开相机就崩溃:补齐 NSCameraUsageDescription 并检查授权状态
相机入口出现 privacy-sensitive data 崩溃时,检查运行 target 的 NSCameraUsageDescription、最终 Info.plist、授权状态与设备可用性,分别处理拒绝和受限分支。
点击扫码或拍照按钮后,应用直接退出,控制台提示 privacy-sensitive data without a usage description,并点名 NSCameraUsageDescription。这类崩溃应先修复应用包中的用途说明:用户还没有机会选择允许或拒绝,系统就发现应用没有声明为什么访问相机。
本文针对 iOS 原生应用通过 AVFoundation 访问摄像头的场景。缺少用途说明在 iOS 10 升级时期尤其常见,当前应用仍需提供这项说明。相机用途说明、用户授权、可用采集设备是三个不同条件;补一个键不会自动满足另外两个。
在正在运行的应用 target 中添加说明
在 Xcode 中选择实际运行的应用 target,打开 Info,添加 Privacy - Camera Usage Description。它对应的原始键是 NSCameraUsageDescription,值应为解释真实功能的字符串,例如扫码功能可以写“用于扫描二维码并读取其中的信息”。
使用显式 Info.plist 文件的项目,可以在根字典中加入:
<key>NSCameraUsageDescription</key>
<string>用于扫描二维码并读取其中的信息</string>
这只是需要合并的键值片段,不是完整 plist 文件。保留现有根字典和其他条目,不要把这个键放进 ATS 配置或某个无关子字典。
多 target 项目要逐个确认:编辑测试 target 的 plist,无法为正式应用补上相机说明。工程若由 Xcode 生成最终 Info.plist,应修改应用 target 的配置,不必为了找不到源码文件而另建一份未参与构建的 plist。
重新构建后,在 Products 中找到应用并查看包内 Info.plist,确认最终产物含有正确键、String 类型和非空的实际用途说明。也可以在调试器暂停于首次访问相机之前,检查主包配置:
po Bundle.main.object(forInfoDictionaryKey: "NSCameraUsageDescription")
这里是 Xcode 调试控制台中的 Swift 表达式,不是终端命令。若返回 nil,先查 target 和构建产物;若值与编辑内容不一致,检查当前构建配置及本地化的 InfoPlist.strings。
在开始采集前处理授权状态
用途说明只提供系统提示文案。真正访问相机前,仍需检查 AVCaptureDevice.authorizationStatus(for: .video):未决定时可以请求授权,已经拒绝或受限制时应显示替代界面。
下面的 Swift 并发示例适用于支持 async/await 的 iOS 15 及以上应用。它只负责准入判断,不负责创建或启动采集会话:
import AVFoundation
@MainActor
func canUseCamera() async -> Bool {
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
return true
case .notDetermined:
return await AVCaptureDevice.requestAccess(for: .video)
case .denied, .restricted:
return false
@unknown default:
return false
}
}
在用户点击相机功能时调用,拿到 true 后才继续配置采集;返回 false 时保留页面,并说明该功能当前不可用。若需要兼容更早系统,可以使用 requestAccess(for:completionHandler:);回调中更新 UIKit 界面前,必须回到主队列或主执行器。
denied 表示用户明确拒绝,重复请求不会让系统每次都弹框。可以给出前往系统设置修改权限的入口,但不要自动反复跳转。restricted 表示当前不允许使用采集设备,不能承诺用户一定能在应用设置中解除。应用从设置回到前台后,应重新读取授权状态,避免继续沿用旧结果。
添加 requestAccess 不能绕过缺失用途说明的问题:调用授权请求本身也可能因未配置说明而触发异常。配置要先进入最终应用包,再验证授权分支。
获得授权后,继续检查设备是否存在
授权成功不代表一定存在可用摄像头。获取设备时保留可选值检查:
// 先完成前面的授权判断,再进入这个分支。
guard let camera = AVCaptureDevice.default(for: .video) else {
// 显示无可用摄像头的界面,结束当前采集准备流程。
return
}
// 在实际采集配置流程中使用 camera;不要强制解包。
模拟器、硬件能力和当前运行环境可能与真机不同,应根据实际返回结果处理。找不到设备、创建输入失败、采集会话中断,与缺少 NSCameraUsageDescription 的崩溃不是同一个问题;继续查看具体错误,不要用新增权限键代替设备和会话排错。
若录像流程实际使用麦克风,还需要单独配置 NSMicrophoneUsageDescription 并处理音频授权。只有扫码、不访问麦克风时,不应为了避免猜测而添加所有权限。把照片保存到相册又涉及独立的照片库访问范围,应按实际保存 API 配置,不能靠相机授权一并取得。
最后分别检查首次请求后允许、首次请求后拒绝、已有授权再次进入、从系统设置改变权限后返回,以及无可用摄像头的分支。用途说明应在首次弹框中正确显示,拒绝和不可用状态应有可退出的界面;只有这些分支都能正常结束,才算修复了相机入口。


