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

Swift 4:二维码扫描成功后及点击确认按钮时关闭扫描器

解决QR扫描后无法关闭相机的问题

嗨,我看到你遇到的问题了——扫描成功后没法关闭相机,核心原因是你把AVCaptureSession定义成了scanButtonTapped方法里的局部变量,方法执行完这个session就被系统释放了,后续点击确认按钮时根本找不到它来停止相机运行。

下面是具体的修复方案,一步步来:

第一步:把AVCaptureSession改成类的属性

在你的ViewController类里,先声明一个全局的session变量,这样整个类的方法都能访问到它:

class YourViewController: UIViewController {
    // 声明全局的捕获会话
    private var captureSession: AVCaptureSession?
    // 如果你用了预览层,也可以在这里声明
    private var previewLayer: AVCaptureVideoPreviewLayer?
    
    // 其他代码...
}

第二步:修改scanButtonTapped方法,使用全局session

把原来方法里的局部session替换成我们刚声明的全局属性:

@objc func scanButtonTapped(sender: UIButton) {
    captureSession = AVCaptureSession()
    guard let captureDevice = AVCaptureDevice.default(for: .video) else {
        self.view.makeToast("无法获取摄像头权限")
        return
    }
    
    do {
        let input = try AVCaptureDeviceInput(device: captureDevice)
        guard let session = captureSession else { return }
        
        if session.canAddInput(input) {
            session.addInput(input)
        }
        
        // 这里添加QR码识别的输出(如果之前没加的话)
        let output = AVCaptureMetadataOutput()
        if session.canAddOutput(output) {
            session.addOutput(output)
            output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
            output.metadataObjectTypes = [.qr]
        }
        
        // 添加预览层到界面(显示相机画面)
        previewLayer = AVCaptureVideoPreviewLayer(session: session)
        previewLayer?.frame = self.view.bounds
        previewLayer?.videoGravity = .resizeAspectFill
        self.view.layer.insertSublayer(previewLayer!, at: 0)
        
        // 启动会话,开始扫描
        session.startRunning()
    } catch {
        self.view.makeToast("抱歉,扫描初始化失败")
        captureSession = nil
        previewLayer?.removeFromSuperlayer()
        previewLayer = nil
    }
}

第三步:实现确认按钮的点击方法,关闭相机

写一个确认按钮的响应方法,在里面停止session,并且清理界面资源:

@objc func confirmButtonTapped(sender: UIButton) {
    // 停止捕获会话,关闭相机
    captureSession?.stopRunning()
    // 移除预览层,恢复界面
    previewLayer?.removeFromSuperlayer()
    // 置空变量,释放资源
    captureSession = nil
    previewLayer = nil
}

额外注意点

  • 别忘了给你的确认按钮绑定这个confirmButtonTapped方法
  • 如果项目里有摄像头权限申请逻辑,要确保用户已经授权,否则相机无法正常启动

这样修改后,点击确认按钮就能正常关闭相机啦~

内容的提问来源于stack exchange,提问作者Yana Shetty

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:30:21