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

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

前言

前面讲了两篇关于如何生成二维码的内容,感兴趣可以先看一下。

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

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

在如今的很多应用里都实现了识别应用内某个图片中二维码的功能,比如最常用的微信,在聊天中就可以长按图片来识别图中的二维码,今天来讲讲如何在 swift 中利用代码识别一张图片中的二维码内容。

CoreImage 识别二维码

其实要识别图片中的二维码内容非常简单,主要用到的是 CoreImage 中的 CIDetector,为了使用方便,我给 UIImage 写了个分类,来专门检测图片上的二维码内容:

swift 复制代码
extension UIImage {
    /// 检测图片中二维码内容
    /// - Returns: 二维码中的内容
    func detectQRCode() -> String? {
        guard let ciImage = ciImage ?? CIImage(image: self) else {
            return nil
        }
        
        let options = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
        let context = CIContext()
        
        guard let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: context, options: options) else {
            return nil
        }
        
        let features = detector.features(in: ciImage)
        
        if let feature = features.first as? CIQRCodeFeature {
            return feature.messageString
        }
        
        return nil
    }
}

简单解释下上边的代码,我们首先将 UIImage 对象转换为 CIImage 对象。然后,我们创建一个 CIDetector 对象并设置识别精度为高。接下来,我们使用该 CIDetector 对象在 CIImage 中查找二维码特征。如果找到了二维码,我们将返回其字符串内容。如果未找到二维码,我们将返回 nil。

使用非常简单,直接拿 UIImage 对象调用 detectQRCode 方法就行了。

识别 UIView 中的二维码

在做类似微信长按识别二维码需求时,可能会针对某个 UIView 下的二维码进行识别,我也为 UIView 写了个分类,来处理这种情况:

swift 复制代码
extension UIView {
    func detectQRCode(completion: @escaping (String?) -> Void) {
        guard let image = self.asImage() else {
            completion(nil)
            return
        }
        DispatchQueue.global(qos: .userInitiated).async {
            let qrCode = image.detectQRCode()
            DispatchQueue.main.async {
                completion(qrCode)
            }
        }
    }
    
    private func asImage() -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, false, UIScreen.main.scale)
        guard let context = UIGraphicsGetCurrentContext() else {
            return nil
        }
        self.layer.render(in: context)
        guard let image = UIGraphicsGetImageFromCurrentImageContext() else {
            return nil
        }
        UIGraphicsEndImageContext()
        return image
    }
}

这个方案的思路是,先将 view 转为图片,然后再使用上一步中写的方法检测图片中的二维码内容。

另外我还考虑到检测二维码的过程可能会比较耗时,所以我把方法改成了异步,检测过程放在了子线程中执行。

使用起来非常方便:

swift 复制代码
// 假设有一个名为 myView 的 UIView 对象
myView.detectQRCode { qrCode in
    if let qrCode = qrCode {
        print("检测到的二维码内容为: \(qrCode)")
    } else {
        print("没有检测到二维码内容")
    }
}

多个二维码的情况

细心的同学可能已经考虑到了,一个图片或者 view 里可能包含多张二维码,那么这种情况也是需要兼容的,其实我们上边的检测方法 detector.features 中返回的是一个数组,里边就包含了所有检测到的对象,我们只需要稍加改动代码,就可以实现这种情况:

swift 复制代码
extension UIImage {
    /// 检测图片中二维码内容
    /// - Returns: 二维码中的内容
    func detectQRCodes() -> [String] {
        guard let ciImage = ciImage ?? CIImage(image: self) else {
            return []
        }
        
        let options = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
        let context = CIContext()
        
        guard let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: context, options: options) else {
            return []
        }
        
        let features = detector.features(in: ciImage)
        
        var qrCodes: [String] = []
        
        for feature in features {
            if let qrCodeFeature = feature as? CIQRCodeFeature {
                if let qrCode = qrCodeFeature.messageString {
                    qrCodes.append(qrCode)
                }
            }
        }
        
        return qrCodes
    }
}

我把这个方法的返回值改成了一个字符串数组,如果图片中包含多个二维码,CIDetectorfeatures(in:) 方法就可以获取所有的二维码特征。然后遍历这些特征,并提取每个二维码的内容。

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

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

相关推荐
HarderCoder42 分钟前
Swift 枚举完全指南——从基础语法到递归枚举的渐进式学习笔记
swift
Digitally1 小时前
如何从iPhone提取照片:2025年的6种方法
ios·iphone
代码s贝多芬的音符9 小时前
ios android 小程序 蓝牙 CRC16_MODBUS
android·ios·小程序
非专业程序员Ping10 小时前
从0到1自定义文字排版引擎:原理篇
ios·swift·assembly·font
2501_9159090610 小时前
“绑定 HTTPS” 的工程全流程 从证书配置到真机验证与故障排查
网络协议·http·ios·小程序·https·uni-app·iphone
2501_9159184111 小时前
iOS 混淆实战 多工具组合完成 IPA 混淆、加固与工程化落地(iOS混淆|IPA加固|无源码混淆|Ipa Guard|Swift Shield)
android·ios·小程序·https·uni-app·iphone·webview
游戏开发爱好者813 小时前
如何系统化掌握 iOS 26 App 耗电管理,多工具协作
android·macos·ios·小程序·uni-app·cocoa·iphone
2501_9159214315 小时前
运营日志驱动,在 iOS 26 上掌握 App 日志管理实践
android·macos·ios·小程序·uni-app·cocoa·iphone
马拉萨的春天16 小时前
iOS的多线程下数据安全和内存泄漏以及工具使用监测内存泄漏
macos·ios·cocoa·多线程
我有与与症1 天前
从0使用Kuikly框架写一个小红书Demo-Day5
客户端