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

Swift4 QR阅读器可运行但无结果,扫描时captureOutput未触发且弹窗不显示

Swift 4 QR码阅读器:captureOutput()未触发的排查与修复

嘿,我之前也碰到过类似的问题,Swift4里AVFoundation的代理坑还真不少!你的问题核心是captureOutput(_:didOutput:from:)没被触发,大概率是这几个地方没做好:

1. 代理设置错误或内存被释放

  • 首先要确保你把AVCaptureMetadataOutput的delegate设为当前ViewController,别随便用weak var(刚启动时如果代理被提前释放,就不会触发回调)。示例代码:
    let metadataOutput = AVCaptureMetadataOutput()
    metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
    
  • 还要确认你已经把这个metadataOutput添加到AVCaptureSession中:
    if session.canAddOutput(metadataOutput) {
        session.addOutput(metadataOutput)
    } else {
        print("无法添加Metadata输出模块")
        return
    }
    

2. 未正确设置识别的元数据类型

Swift4里AVFoundation用枚举替代了旧的字符串常量,如果你没明确指定要识别QR码,系统不会触发回调。一定要加上:

metadataOutput.metadataObjectTypes = [.qr]

注意:别用AVMetadataObjectTypeQRCode这种旧写法,Swift4里必须用枚举值.qr。

3. 代理方法签名完全匹配

这是最容易踩的坑!如果方法签名哪怕差一点点,系统都不会调用它。Swift4里正确的签名应该是:

func captureOutput(_ output: AVCaptureOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
    // 在这里处理扫描到的QR码,比如弹出弹窗
    guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject else { return }
    if metadataObject.type == .qr {
        if let qrCodeString = metadataObject.stringValue {
            print("扫描到QR码:\(qrCodeString)")
            // 弹出提示弹窗
            let alert = UIAlertController(title: "扫描成功", message: qrCodeString, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "确定", style: .default))
            present(alert, animated: true)
            // 可选:暂停扫描
            session.stopRunning()
        }
    }
}

检查一下你的方法参数名、类型有没有写错,比如是不是把[AVMetadataObject]写成了[Any],或者参数顺序搞反了?

4. 相机权限与会话运行状态

  • 确保你已经在Info.plist里添加了NSCameraUsageDescription权限描述,否则相机可能无法正常启动,哪怕你调用了session.startRunning()。
  • 确认session.startRunning()是在主线程调用的,或者在相机权限获取成功后才执行:
    AVCaptureDevice.requestAccess(for: .video) { granted in
        if granted {
            DispatchQueue.main.async {
                self.session.startRunning()
            }
        } else {
            print("用户拒绝了相机权限")
        }
    }
    

快速排查技巧

  • 在session.startRunning()之后加print("会话已启动:\(session.isRunning)"),确认会话真的在运行。
  • 在captureOutput方法开头加print("触发了回调!"),看控制台有没有输出,就能直接判断是不是方法没被调用。

内容的提问来源于stack exchange,提问作者Eric Chong

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 07:03:06