Flutter项目集成AVFoundation扫码无画面问题求助
问题排查与解决方案
你的问题核心是相机预览画面不显示,同时存在AVCaptureSession startRunning在主线程调用的性能警告,以下是针对性的修复步骤:
1. 修复预览层布局问题(核心原因)
在setUpView方法中,直接用_view.layer.bounds设置previewLayer.frame时,_view的布局尚未完成,bounds可能是初始零值或错误尺寸,导致预览层无法正常显示。
解决方案:
添加视图布局监听,在视图尺寸变化时实时更新预览层的frame:
private func setUpView(){ _view.backgroundColor = UIColor.clear captureSession = AVCaptureSession() // 可选:设置会话预设为高清,提升扫描清晰度 captureSession.sessionPreset = .high guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else { return } let videoInput: AVCaptureDeviceInput do { videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice) } catch { print("相机输入初始化失败:\(error)") return } if (captureSession.canAddInput(videoInput)) { captureSession.addInput(videoInput) } else { failed() return } let metadataOutput = AVCaptureMetadataOutput() if (captureSession.canAddOutput(metadataOutput)) { captureSession.addOutput(metadataOutput) // 改用后台队列处理元数据,避免阻塞主线程 let metadataQueue = DispatchQueue(label: "com.ceal.qr.metadata") metadataOutput.setMetadataObjectsDelegate(self, queue: metadataQueue) metadataOutput.metadataObjectTypes = [.qr] } else { failed() return } previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) previewLayer.videoGravity = .resizeAspectFill _view.layer.addSublayer(previewLayer) // 添加布局监听,实时更新预览层尺寸 _view.addObserver(self, forKeyPath: "bounds", options: [.new], context: nil) // 移到后台线程启动会话,解决性能警告 DispatchQueue.global(qos: .userInitiated).async { self.captureSession.startRunning() } } // 实现监听回调 override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "bounds" { previewLayer.frame = _view.layer.bounds } } // 在deinit中移除监听,避免内存泄漏 deinit { _view.removeObserver(self, forKeyPath: "bounds") captureSession?.stopRunning() }
2. 修复线程警告问题
AVCaptureSession.startRunning()是耗时操作,必须放在后台线程执行,否则会导致主线程阻塞、UI卡顿。上面的代码已将其移到DispatchQueue.global(qos: .userInitiated)后台队列中。
3. 额外优化点
- 元数据队列优化:将元数据回调的队列从
DispatchQueue.main改为自定义后台队列,避免扫描时的UI卡顿。 - 会话预设设置:添加
captureSession.sessionPreset = .high,确保相机输出足够清晰的画面,提升二维码识别成功率。 - 错误日志补充:在
do-catch块中添加错误打印,方便排查相机初始化失败的具体原因。
4. 验证权限配置
请确认Info.plist中已添加NSCameraUsageDescription键,并填写合理的权限说明文本,否则权限申请会被系统拒绝:
<key>NSCameraUsageDescription</key> <string>需要访问相机以扫描二维码</string>
完成以上修改后,相机预览画面应该能正常显示,同时线程警告也会消失。
内容的提问来源于stack exchange,提问作者BraveEvidence
相关产品推荐
相关产品推荐

