Swift 4 相机访问方法及扫码报错‘Failed to get the camera device’求助
我来给你捋捋在Swift 4里访问相机的常规步骤,亲测靠谱:
第一步:配置相机权限
必须在Info.plist中添加相机权限描述,不然系统会直接拒绝访问。右键Info.plist选择“Open As -> Source Code”,添加以下代码:<key>NSCameraUsageDescription</key> <string>需要访问相机进行拍摄/扫码操作</string>字符串内容要明确告诉用户为什么需要相机权限,别写空字符串或者模糊的描述。
第二步:用AVFoundation框架实现访问逻辑
Swift 4中访问相机主要依赖AVFoundation框架,下面是核心代码示例:import AVFoundation import UIKit class CameraViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate { var captureSession: AVCaptureSession! var previewLayer: AVCaptureVideoPreviewLayer! override func viewDidLoad() { super.viewDidLoad() // 先请求相机权限 AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in DispatchQueue.main.async { guard granted else { // 权限被拒绝,提示用户去设置里开启 let alert = UIAlertController(title: "权限不足", message: "请在设置中开启相机权限", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) self?.present(alert, animated: true) return } // 权限通过,初始化相机会话 self?.setupCameraSession() } } } func setupCameraSession() { captureSession = AVCaptureSession() captureSession.sessionPreset = .high // 获取后置相机设备 guard let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else { print("无法获取相机设备") return } // 创建输入流 guard let input = try? AVCaptureDeviceInput(device: captureDevice) else { print("无法创建相机输入") return } if captureSession.canAddInput(input) { captureSession.addInput(input) } // 创建输出流(如果需要处理视频帧,比如扫码) let videoOutput = AVCaptureVideoDataOutput() videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "cameraQueue")) if captureSession.canAddOutput(videoOutput) { captureSession.addOutput(videoOutput) } // 添加预览层到视图 previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) previewLayer.frame = view.bounds previewLayer.videoGravity = .resizeAspectFill view.layer.addSublayer(previewLayer) // 启动会话 captureSession.startRunning() } // 实现视频帧代理方法(如果需要处理帧数据) func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { // 在这里处理每帧视频数据,比如扫码逻辑 } }注意事项
- 相机操作必须在真机上测试,模拟器没有相机硬件;
- 权限请求是异步的,一定要等用户授权后再初始化相机会话;
- 如果需要切换前后摄像头,可以用
AVCaptureDevice.DiscoverySession枚举可用设备。
我之前帮朋友排查过类似的问题,正好也用过你提到的这个扫码仓库代码,给你几个针对性的排查方向:
可能的原因&解决方法:
权限配置是否真的正确?
有时候看似加了权限,其实键名拼写错误或者描述为空。确认Info.plist中的NSCameraUsageDescription(对应可视化界面的“Privacy - Camera Usage Description”)存在,且字符串内容不为空。有些iOS版本会因为描述为空直接拒绝权限,导致无法获取相机。相机设备获取逻辑不够兼容
原仓库代码可能用了AVCaptureDevice.default(for: .video)来获取相机,但有些旧设备(比如iPhone SE初代)或者特殊机型上,这个方法可能返回nil。建议把获取设备的代码改成更稳妥的写法:// 替换原有的获取相机设备代码 let discoverySession = AVCaptureDevice.DiscoverySession( deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .back ) guard let captureDevice = discoverySession.devices.first else { print("Failed to get the camera device") return }这种方式会枚举所有可用的后置广角相机,兼容性更好。
权限请求时机不对
有些代码会在权限请求还没完成时就初始化相机,导致权限还没通过就尝试获取设备。确保把相机初始化的代码放在权限请求的completion handler里,并且切换到主线程执行(比如我第一个问题里的代码示例那样)。硬件或系统问题
试试重启你的真机,有时候后台有其他应用占用相机,会导致当前应用无法获取;或者换一台真机测试,排除硬件故障的可能。检查项目依赖
确认你的项目已经正确导入AVFoundation框架,用CocoaPods安装的话,仓库应该已经配置好了,但手动导入的话要确保在Build Phases的Link Binary With Libraries里添加了AVFoundation.framework。
内容的提问来源于stack exchange,提问作者OCTAVIAN

