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

下面就是详细讲解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自带原生二维码扫描。

阅读剩余 78%

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

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

相关文章

  • Win11家庭版怎么开启组策略? Win11家庭版添加组策略的技巧

    Win11家庭版怎么开启组策略 Win11家庭版默认情况下没有组策略编辑器(Group Policy Editor),但是我们可以通过一些技巧来开启组策略功能。下面是详细的攻略: 步骤一:创建组策略编辑器快捷方式 在桌面上右键点击空白处,选择“新建” -> “快捷方式”。 在弹出的窗口中,输入以下路径并点击“下一步”: %windir%\\system…

    other 2023年8月5日
    00
  • C语言编程函数指针入门精讲教程

    首先,需要明确函数指针的概念:函数指针是指向函数的指针变量。通过函数指针,我们可以将函数名作为一个参数传递给另一个函数,或者在一个函数中返回一个函数名,从而实现函数的动态调用。 接下来,我们可以按照以下步骤进行函数指针的使用: 1. 声明函数指针类型 在使用函数指针之前,我们需要先定义函数指针类型。函数指针类型的定义方式为:指针类型名 (*函数指针名)(参数…

    other 2023年6月27日
    00
  • 深入讲解Java编程中类的生命周期

    深入讲解Java编程中类的生命周期攻略 什么是类? Java编程中,类是指一种数据类型,继承了Object类的方法和属性,是面向对象编程的基本概念之一。类是Java编写的基本单位,在类中定义了变量和方法,并行定义了数据的类型和操作该数据的方法。 类的生命周期 类的生命周期可以分为以下四个阶段: 加载:当Java程序需要使用一个类时,会通过类加载器将该类的字节…

    other 2023年6月20日
    00
  • Vue实现记住账号密码功能的操作过程

    下面是Vue实现记住账号密码功能的操作过程: 1. 本地存储 要实现记住账号密码功能,我们需要在客户端上保存用户输入的账号密码信息。对于前端开发而言,最常用的本地存储方式就是localStorage。localStorage是HTML5标准中新加入的一个W3C Web Storage API,主要用于浏览器本地离线存储一些键值对数据,用来存储一些长期的持久性…

    other 2023年6月27日
    00
  • Java中String对象的深入理解

    Java中String对象的深入理解 String是Java中最常用的类之一,用于表示字符串。在Java中,String对象是不可变的,这意味着一旦创建了String对象,就不能修改其内容。在本攻略中,我们将深入理解Java中String对象的特性和用法。 1. String的创建和初始化 在Java中,有多种方式可以创建和初始化String对象: 直接赋值…

    other 2023年10月15日
    00
  • 超星尔雅12倍速播放脚本

    当然,我很乐意为您提供“超星尔雅12倍速播放脚本”的完整攻略。以下是详细的步骤和示例说明: 安装脚本 要安装“超星尔雅12倍速播放脚本”,需要先安装Tampermonkey插件。Tampermonkey是一款浏览器插件,可以用于管理用户脚本。以下是安装Tampermonkey的步: 打开浏览器,访问Tampermonkey官网(https://www.tam…

    other 2023年5月8日
    00
  • 详解nuxt sass全局变量(公共scss解决方案)

    详解Nuxt Sass全局变量(公共SCSS解决方案) 在Nuxt.js中,我们可以使用Sass来管理样式,并且可以通过全局变量来共享样式属性。这个攻略将详细介绍如何在Nuxt.js项目中设置全局Sass变量,并在组件中使用它们。 步骤1:安装依赖 首先,确保你的Nuxt.js项目已经安装了sass-loader和node-sass依赖。如果没有安装,可以通…

    other 2023年7月29日
    00
  • Linux Shell函数返回值

    Linux Shell函数返回值攻略 在Linux Shell中,函数是一种将一系列命令组合在一起以完成特定任务的方法。函数可以接受参数,并且可以返回一个值作为结果。本攻略将详细讲解如何在Linux Shell中使用函数并获取返回值。 定义函数 要定义一个函数,可以使用以下语法: function_name() { # 函数体 # 可以包含一系列命令 # 可…

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