iOS自带原生二维码扫描的实现

yizhihongxing

下面就是详细讲解iOS自带原生二维码扫描的实现的完整攻略:

一、引入AVFoundation库

首先,我们需要引入AVFoundation库,来实现二维码扫描。在xcode中选择你项目的targets中的Build Phases,在Link Binary With Libraries中添加AVFoundation.framework。

二、继承AVCaptureSession,创建二维码捕捉器

我们需要继承AVCaptureSession,并创建一个二维码捕捉器来扫描二维码。可以看下面的示例:

import AVFoundation

class QRCodeScanner {
    let captureSession = AVCaptureSession()
    var previewLayer: AVCaptureVideoPreviewLayer?

    init() {
        guard let captureDevice = AVCaptureDevice.default(for: .video),
            let input = try? AVCaptureDeviceInput(device: captureDevice) else {
            return
        }

        let captureMetadataOutput = AVCaptureMetadataOutput()
        captureSession.addInput(input)
        captureSession.addOutput(captureMetadataOutput)

        captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        captureMetadataOutput.metadataObjectTypes = [.qr]

        let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer.videoGravity = .resizeAspectFill
        self.previewLayer = previewLayer
    }
}

以上代码中,我们使用AVCaptureSession来创建了一个二维码捕捉器QRCodeScanner。先检测一下设备是否有摄像头,并创建AVCaptureDeviceInput输入设备。然后,创建AVCaptureMetadataOutput对象来检测捕捉到的二维码。最后,创建了一个AVCaptureVideoPreviewLayer预览图层并添加到self.previewLayer中。

三、实现AVCaptureMetadataOutputObjectsDelegate代理方法

接下来,我们需要实现AVCaptureMetadataOutputObjectsDelegate代理方法,来处理捕捉到的二维码。具体代码如下:

extension QRCodeScanner: AVCaptureMetadataOutputObjectsDelegate {
    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
            let stringValue = metadataObject.stringValue,
            metadataObject.type == .qr else {
            return
        }

        // 二维码扫描成功,可以在这里执行回调
    }
}

以上代码中,我们处理捕捉到的AVMetadataObject,将其转换为二维码AVMetadataMachineReadableCodeObject对象,并获取到二维码的stringValue,来完成二维码的扫描。如果扫描的不是二维码,则直接返回。

四、启动二维码扫描

在上面的QRCodeScanner实现中,我们创建好了AVCaptureSession的输入和输出,以及预览图层。接下来,启动二维码扫描即可:

class ViewController: UIViewController {

    private var qrCodeScanner: QRCodeScanner!

    override func viewDidLoad() {
        super.viewDidLoad()
        qrCodeScanner = QRCodeScanner()

        guard let previewLayer = qrCodeScanner.previewLayer else { return }
        previewLayer.frame = view.layer.bounds
        view.layer.addSublayer(previewLayer)

        qrCodeScanner.captureSession.startRunning()
    }
}

在上面代码中,我们创建了一个QRCodeScanner对象qrCodeScanner,并把预览图层添加到UIViewController的view上。最后,启动QRCodeScanner的捕捉器captureSession即可。

五、示例说明

接下来,我给你两个示例,具体实现请参考上面的完整攻略:

示例1:在UIAlertController中展示扫描到的二维码

在QRCodeScanner中实现接口扫描结束的回调

class QRCodeScanner {
    var onQRCodeScanned: ((String) -> Void)?

    // ...

    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
            let stringValue = metadataObject.stringValue,
            metadataObject.type == .qr else {
            return
        }

        // 扫描到二维码,执行回调
        onQRCodeScanned?(stringValue)
    }
}

在UIViewController中弹出UIAlertController,展示扫描到的二维码

class ViewController: UIViewController {

    private var qrCodeScanner: QRCodeScanner!

    override func viewDidLoad() {
        super.viewDidLoad()
        qrCodeScanner = QRCodeScanner()

        qrCodeScanner.onQRCodeScanned = { [weak self] qrCodeString in
            self?.showQRCodeInfo(qrCodeString)
        }

        guard let previewLayer = qrCodeScanner.previewLayer else { return }
        previewLayer.frame = view.layer.bounds
        view.layer.addSublayer(previewLayer)

        qrCodeScanner.captureSession.startRunning()
    }

    private func showQRCodeInfo(_ qrCodeInfo: String) {
        let alertController = UIAlertController(title: "扫描到的二维码", message: qrCodeInfo, preferredStyle: .alert)
        let okAction = UIAlertAction(title: "确定", style: .default, handler: nil)
        alertController.addAction(okAction)

        present(alertController, animated: true, completion: nil)
    }
}

示例2:在UITableView中展示扫描到的二维码

在QRCodeScanner中实现接口扫描结束的回调

class QRCodeScanner {
    var onQRCodeScanned: ((String) -> Void)?

    // ...

    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        guard let metadataObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
            let stringValue = metadataObject.stringValue,
            metadataObject.type == .qr else {
            return
        }

        // 扫描到二维码,执行回调
        onQRCodeScanned?(stringValue)
    }
}

在UIViewController中添加UITableView,并更新数据源展示二维码信息

class ViewController: UIViewController {

    private var qrCodeScanner: QRCodeScanner!
    private var qrCodeStrings = [String]() {
        didSet {
            tableView.reloadData()
        }
    }
    private let tableView = UITableView()

    override func viewDidLoad() {
        super.viewDidLoad()
        qrCodeScanner = QRCodeScanner()

        qrCodeScanner.onQRCodeScanned = { [weak self] qrCodeString in
            self?.qrCodeStrings.append(qrCodeString)
        }

        guard let previewLayer = qrCodeScanner.previewLayer else { return }
        previewLayer.frame = view.layer.bounds
        view.layer.addSublayer(previewLayer)

        qrCodeScanner.captureSession.startRunning()

        setupTableView()
    }

    private func setupTableView() {
        view.addSubview(tableView)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            tableView.topAnchor.constraint(equalTo: view.topAnchor),
            tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
        ])
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "qrCodeCell")
        tableView.dataSource = self
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return qrCodeStrings.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "qrCodeCell", for: indexPath)
        let qrCodeString = qrCodeStrings[indexPath.row]
        cell.textLabel?.text = qrCodeString
        return cell
    }
}

以上示例代码很简单,你可以尝试在自己的项目中按照上述方法实现iOS自带原生二维码扫描。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:iOS自带原生二维码扫描的实现 - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • iDempiere 使用指南 绿色版一键启动测试环境

    iDempiere 使用指南 绿色版一键启动测试环境 开发测试环境的设置是 iDempiere 实现数字化转型必不可少的一步。在使用 iDempiere 时,搭建一个安全可靠的测试环境是非常重要的。为了帮助 iDempiere 用户更加方便地搭建测试环境,我们发布了 iDempiere 使用指南 绿色版一键启动测试环境。 iDempiere 简介 iDemp…

    其他 2023年3月28日
    00
  • android自定义view制作圆形进度条效果

    下面我将为你详细讲解Android自定义View制作圆形进度条效果的完整攻略。 一、前置知识 在学习制作圆形进度条之前,我们需要掌握以下一些知识: Android自定义View的基本原理 画笔(Paint)的使用 Canvas的使用 如果你对这些知识还不是很熟悉,可以查看相关的资料和学习。 二、绘制圆形进度条的原理 实现圆形进度条的关键在于理解角度的概念,以…

    other 2023年6月25日
    00
  • 为什么要学习C语言 C语言优势分析

    为什么要学习C语言? C语言是一门广泛使用的计算机编程语言。许多操作系统、程序和应用软件都是用C语言进行开发的,而且C语言的语法和结构对于初学者来说比其他高级语言更为基础。此外,C语言还有以下优势: 1. 速度和效率高 C语言编译后可以生成高效的机器码,因此C语言的程序能够在计算机中快速地运行。同时,C语言直接对计算机的底层进行控制,可以实现高效的内存管理和…

    other 2023年6月27日
    00
  • Python重写父类的三种方法小结

    下面我将详细讲解Python重写父类的三种方法小结。 一、继承父类并重写 这种方法就是我们平时最常用到的方法了,我们通过继承父类,在子类中重写父类的方法,来实现自己想要的功能。 示例代码: class Animal: def __init__(self, name): self.name = name def run(self): print(self.na…

    other 2023年6月27日
    00
  • 配置接口切换到三层模式

    以下是关于“配置接口切换到三层模式”的完整攻略,包括基本概念、步骤和两个示例。 基本概念 在Java开发中,三层模式是一常用的设计模式,它将应用程序分三个层:表示层、业务逻辑层和数据访问层。表示层负责与交互,业务逻辑层负责处理业务逻辑,数据访问层负责与数据库交互。使用三层模式可以提高应用的可维护性和可扩展性。 步骤 以下将接口切换到三层模式的步骤: 创建表示…

    other 2023年5月7日
    00
  • go环境变量配置(goroot和gopath)

    go环境变量配置(goroot和gopath) Go语言是一门开发高并发、高可靠性、高性能程序的语言,近年来越来越受到开发者的青睐。在进行Go开发之前,需要先进行go环境变量的配置。本文将详细介绍Go环境变量配置步骤,其中包括goroot和gopath的配置。 goroot goroot是指go的安装目录。在使用Go语言开发之前,需要先安装Go语言。安装Go…

    其他 2023年3月28日
    00
  • CentOS如何设置终端显示字符界面区域的大小?

    下面是CentOS如何设置终端显示字符界面区域的大小的完整攻略: 1. 查看当前终端的窗口大小 在终端中输入以下命令,即可查看当前终端窗口的大小: $ stty size 该命令输出两个数字,第一个数字表示行数,第二个数字表示列数。例如: $ stty size 24 80 表示当前终端窗口为24行、80列。 2. 设置终端窗口大小 要设置终端窗口的大小,可…

    other 2023年6月27日
    00
  • opengl中fbo的概念及其应用[转]

    OpenGL中FBO的概念及其应用 FBO(Frame Buffer Object)是OpenGL中的一个重要概念,它可以用于离屏渲染和后期处理等应用。本文将提供一个完整攻略,介绍FBO概念及其应用,并供两个示例说明。 FBO的概念 FBO是OpenGL中的一个对象,它可以用于离屏渲染和后期处理等应。FBO包含一个或多个附加点(Attachment Poin…

    other 2023年5月8日
    00
合作推广
合作推广
分享本页
返回顶部