开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情
最近项目里面开发扫码功能,需要支持二维码和条形码解析,因为系统api就已经支持,所以此处只使用原生api,记录一下开发过程中遇到的一些问题
1. rectOfInterest(扫描区域)的设置
rectOfInterest在文档里面的解释是:
The value of this property is a CGRect that determines the receiver's rectangle of interest for each frame of video. The rectangle's origin is top left and is relative to the coordinate space of the device providing the metadata. Specifying a rectOfInterest may improve detection performance for certain types of metadata. The default value of this property is the value CGRectMake(0, 0, 1, 1). Metadata objects whose bounds do not intersect with the rectOfInterest will not be returned.
简单的解释来说就是:有效的扫描区域,定位是以设置的右顶点为原点。屏幕宽所在的那条线为y轴,屏幕高所在的线为x轴,即CGRectMake(y, x, h, w),其值介于 0 -- 1,如果设置为 CGRectMake(0, 0, 1, 1) 将是全屏幕扫描; 所以需要将我们的扫描框的坐标(相对于设备), 转换为 0--1 之间的值(相对于图像).
我的设置代码如下:
let x1 = (kScreenWidth - 288)/2
let y1 = k_Height_NavigationtBarAndStatuBar + 16
let w1 = 288.0
let h1 = 260.0
//设置扫描区域
deviceOutput.rectOfInterest = CGRect.init(x: y1/kScreenHeight, y: x1/kScreenWidth, width: h1/kScreenHeight, height: w1/kScreenWidth)
2. metadataObjectTypes
设置扫码支持的编码格式(如下设置条形码和二维码兼容)
deviceOutput.metadataObjectTypes = [.qr, .ean13, .ean8, .code128]
这里遇到的一个问题是,在iOS16.1上,无法同时兼容条形码和二维码的扫描,详情如iOS 16 native scan code rectOfInte… | Apple Developer Forums
在最新的iOS16.3上已经修复了这个问题
3. 从相册获取图片识别二维码和条形码
之前项目里面用到的都是识别二维码,要支持二维码和条形码的话,需要使用Vision这个系统库
import Vision
/// 识别二维码和条形码
func parseBarCode(img: UIImage) {
guard let cgimg = img.cgImage else {
return
}
let request = VNDetectBarcodesRequest { req, err in
if let error = err {
print("parseBarCode error: \(error)")
return
}
guard let results = req.results, results.count > 0 else {
return
}
for result in results {
if let barcode = result as? VNBarcodeObservation, let value = barcode.payloadStringValue {
if barcode.symbology == .qr { // 二维码
print("qrcode: \(value)")
}else { // 条形码
print("barcode: \(value), \(barcode.symbology.rawValue)")
}
break
}
}
}
let handler = VNImageRequestHandler(cgImage: cgimg)
do {
try handler.perform([request])
} catch {
print("parseBarCode error: \(error)")
}
}