You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS App因相机权限崩溃:已配置NSCameraUsageDescription仍报错

二维码扫描相机权限崩溃问题排查

问题背景

打开二维码扫描视图控制器时App直接崩溃,报错内容如下:

This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSCameraUsageDescription key with a string value explaining to the user how the app uses this data.

已反复检查Info.plist文件及Target配置,确认添加了相机权限描述,但错误仍未解决。相关ViewController代码如下:

import UIKit
import AVFoundation

class Scanner__VC: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
    var captureSession: AVCaptureSession!
    var previewLayer: AVCaptureVideoPreviewLayer!

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = UIColor.black
        captureSession = AVCaptureSession()

        guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else { return }
        let videoInput: AVCaptureDeviceInput

        do {
            videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
        } catch {
            return
        }

        if (captureSession.canAddInput(videoInput)) {
            captureSession.addInput(videoInput)
        } else {
            failed()
            return
        }

        let metadataOutput = AVCaptureMetadataOutput()

        if (captureSession.canAddOutput(metadataOutput)) {
            captureSession.addOutput(metadataOutput)
            metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
            metadataOutput.metadataObjectTypes = [.qr]
        } else {
            failed()
            return
        }

        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer.frame = view.layer.bounds
        previewLayer.videoGravity = .resizeAspectFill
        view.layer.addSublayer(previewLayer)

        captureSession.startRunning()
    }

    func failed() {
        let ac = UIAlertController(title: "Scanning not supported", message: "Your device does not support scanning a code from an item. Please use a device with a camera.", preferredStyle: .alert)
        ac.addAction(UIAlertAction(title: "OK", style: .default))
        present(ac, animated: true)
        captureSession = nil
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if (captureSession?.isRunning == false) {
            captureSession.startRunning()
        }
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if (captureSession?.isRunning == true) {
            captureSession.stopRunning()
        }
    }

    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        captureSession.stopRunning()

        if let metadataObject = metadataObjects.first {
            guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
            guard let stringValue = readableObject.stringValue else { return }
            AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
            found(code: stringValue)
        }

        dismiss(animated: true)
    }

    func found(code: String) {
        print(code)
    }

    override var prefersStatusBarHidden: Bool {
        return true
    }

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .portrait
    }

    func showAlert(with message: String) {
        let alert = UIAlertController(title: "QR Code Scanned", message: message, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        present(alert, animated: true)
    }
}

可能的遗漏配置及修复方案

  • 检查权限键名拼写:确保Info.plist中添加的是NSCameraUsageDescription(注意大小写和完整拼写,避免少写字母或写错单词),iOS 10及以上版本必须使用该键名。
  • 确认配置文件对应正确Target:项目中可能存在多个Info.plist(如主App、Extension的配置),需验证添加权限的是当前运行Target对应的Info.plist。可通过Target的「Build Settings」→「Info.plist File」路径确认文件位置。
  • 保证权限描述非空:权限对应的字符串值不能为空,必须填写明确的用途说明(例如“需要访问相机以扫描二维码”),空值会被系统判定为未配置权限。
  • 清理缓存并重启Xcode:Xcode可能缓存旧配置,执行「Product」→「Clean Build Folder」,重启Xcode后重新编译运行。
  • 调整权限申请时机:代码中在viewDidLoad直接启动captureSession.startRunning(),但iOS要求权限弹窗需由用户交互触发(如按钮点击)。建议将相机启动逻辑移至用户主动操作(比如点击“开始扫描”按钮)之后,避免系统拦截权限申请。
  • 验证编译后包的配置:右键点击编译生成的.app文件→「Show Package Contents」,打开其中的Info.plist,确认NSCameraUsageDescription键和对应值是否存在,验证配置是否被正确打包。

内容的提问来源于stack exchange,提问作者Hamza Imran

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 05:07:20