iOS 中如何用摄像头扫描二维码

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

之前讲过一些识别和生成二维码的技术文章,感兴趣可以去看看:

二维码 1: 如何用 swift 生成二维码

二维码 2: 如何用 swift 设置二维码的样式

二维码 3: 如何识别图片中的二维码内容

但是一直没有讲如何用摄像头扫描二维码,iOS 其实内置了扫描二维码的支持,使用的是 AVFoundation 这个库,但要想做好一个二维码的识别,还不是那么容易,你需要创建捕获会话、创建预览层、处理代理回调等。

今天来简单讲讲如何在 iOS 中识别二维码。

AVCaptureSession

要在 iOS 中识别二维码,主要用到的是 AVCaptureSession 这个类,首先导入 AVFoundation,然后我们在控制器中创建一个 session 对象:

swift 复制代码
import AVFoundation
let session = AVCaptureSession()

检查摄像头权限

在开始前,你需要检查是否有摄像头权限:

swift 复制代码
func checkCameraPermission() {
    let authStatus = AVCaptureDevice.authorizationStatus(for: .video)

    switch authStatus {
    case .authorized:
        print("已经授权,可以使用摄像头")
    case .denied:
        print("用户拒绝授权,无法使用摄像头")
    case .restricted:
        print("用户无法授权,比如家长控制等情况")
    case .notDetermined:
        print("用户还没有做出选择")
    @unknown default:
        print("其他未知情况")
    }
}

配置

检查有权限之后需要做一些配置:

scss 复制代码
func configs() {
    /// 获取设备
    let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .back)
    /// 输入和输出
    if let firstDevice = discoverySession.devices.first,
       let videoInput = try? AVCaptureDeviceInput(device: firstDevice) {
        let queue = DispatchQueue.global(qos: .default)
        let videoOutput = AVCaptureMetadataOutput()
        videoOutput.setMetadataObjectsDelegate(self, queue: queue)
        // 添加输入
        if session.canAddInput(videoInput) {
            session.addInput(videoInput)
        }
        // 添加输出
        if session.canAddOutput(videoOutput) {
            session.addOutput(videoOutput)
        }
        /// 设置扫描类型
        videoOutput.metadataObjectTypes = [            .qr,            .code39,            .code128,            .code39Mod43,            .ean13,            .ean8,            .code93]
    } else {
        print("出错")
    }
}

添加预览

预览就是把摄像头拍到的内容显示出来,我们这里直接全屏显示:

ini 复制代码
func addPreview() {
    let previewLayer = AVCaptureVideoPreviewLayer(session: session)
    previewLayer.frame = view.layer.bounds
    previewLayer.videoGravity = .resizeAspectFill
    view.layer.addSublayer(previewLayer)
}

开始扫描

之后就可以调用开始扫描的方法了:

scss 复制代码
session.startRunning()

扫描结果需要实现 AVCaptureMetadataOutputObjectsDelegate 这个代理:

swift 复制代码
extension ViewController: AVCaptureMetadataOutputObjectsDelegate {
    /// 扫描结果回调
    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        
        guard !metadataObjects.isEmpty else {
            print("扫描结果为空")
            return
        }
        for object in metadataObjects {
            if let obj = object as? AVMetadataMachineReadableCodeObject,
               let result = obj.stringValue {
                print("扫描结果为:\(result)")
            }
        }
        
        // 停止扫描
        session.stopRunning()
        // 扫到之后的操作。。。
    }
}

一般来说,扫描到内容之后需要停止 Session 的扫描,并对扫描结果进行处理。

这里每天分享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
2501_9151063214 小时前
App HTTPS 抓包 工程化排查与工具组合实战
网络协议·ios·小程序·https·uni-app·php·iphone
2501_9160088916 小时前
金融类 App 加密加固方法,多工具组合的工程化实践(金融级别/IPA 加固/无源码落地/Ipa Guard + 流水线)
android·ios·金融·小程序·uni-app·iphone·webview
2501_9159214317 小时前
Fastlane 结合 开心上架(Appuploader)命令行版本实现跨平台上传发布 iOS App 免 Mac 自动化上架实战全解析
android·macos·ios·小程序·uni-app·自动化·iphone
游戏开发爱好者818 小时前
iOS 上架要求全解析,App Store 审核标准、开发者准备事项与开心上架(Appuploader)跨平台免 Mac 实战指南
android·macos·ios·小程序·uni-app·iphone·webview
qixingchao18 小时前
iOS SwiftUI 动画开发指南
ios·swiftui·swift
alengan19 小时前
ios支付
macos·ios·cocoa
00后程序员张19 小时前
混淆 iOS 类名与变量名的实战指南,多工具组合把混淆做成工程能力(混淆 iOS 类名变量名/IPA 成品混淆Ipa/Guard CLI 实操)
android·ios·小程序·https·uni-app·iphone·webview
MrZWCui20 小时前
iOS app语言切换
macos·ios·cocoa
晴天无痕21 小时前
iOS修改tabbar的背景图
macos·ios·cocoa
Digitally21 小时前
5 种无需 iTunes 将 iPad 照片传输到电脑的方法
ios·电脑·ipad