iOS系统自带的扫码功能(二维码+条形码+识别本地图片)
扫码采用类库:AVFoundation
1、相关权限
1)、需要在info.plist中添加以下权限:Privacy - Camera Usage Description(使用摄像机的权限说明)
2)、权限申请与判断:
查询权限:AVCaptureDevice.authorizationStatus(for: .video)
申请权限:AVCaptureDevice.requestAccess(for: .video)
2、初始化摄像头
// 查找广角摄像头 let deviceDiscovery = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .back) guard let device = deviceDiscovery.devices.last else { return } guard let deviceInput = try? AVCaptureDeviceInput(device: device) else { return } if sesson.canAddInput(deviceInput) { sesson.addInput(deviceInput) } // 初始化元数据输出管道,用于识别条码,二维码 let metaDataOutput = AVCaptureMetadataOutput() metaDataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main) if sesson.canAddOutput(metaDataOutput) { sesson.addOutput(metaDataOutput) } // 设置元数据识别类型 qr:二维码;其他:条形码 metaDataOutput.metadataObjectTypes = [.qr, .ean13, .ean8, .upce, .code39, .code39Mod43, .code93, .code128, .pdf417] // 初始化视频预览图层 let previewLayer = AVCaptureVideoPreviewLayer(session: sesson) previewLayer.videoGravity = .resizeAspectFill previewLayer.frame = view.bounds view.layer.insertSublayer(previewLayer, at: 0) // 设置元数据识别区域(只有在该区域内的内容才会被识别) metaDataOutput.rectOfInterest = scanRect sesson.startRunning()
3、添加二维码与条形码识别输出管道:
// 初始化元数据输出管道,用于识别条码,二维码 let metaDataOutput = AVCaptureMetadataOutput() metaDataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main) if sesson.canAddOutput(metaDataOutput) { sesson.addOutput(metaDataOutput) } // 设置元数据识别类型 qr:二维码;其他:条形码 metaDataOutput.metadataObjectTypes = [.qr, .ean13, .ean8, .upce, .code39, .code39Mod43, .code93, .code128, .pdf417] // 设置元数据识别区域(只有在该区域内的内容才会被识别) metaDataOutput.rectOfInterest = scanRect
管道回调代理:
extension ScannerViewController: AVCaptureMetadataOutputObjectsDelegate { public func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { guard metadataObjects.count > 0 else { return } let texts = metadataObjects.compactMap { data -> String? in guard let code = data as? AVMetadataMachineReadableCodeObject else { return nil } return code.stringValue // 识别结果 } } }
以上就是一个完整的扫码功能。
接下来就是识别本地的条形码和二维码图片
系统提供两种方法识别二维码:其中用到了Vision库->VNDetectBarcodesRequest
/// 仅仅识别二维码图片 public static func parseQRCode(img: UIImage) -> String? { guard let ciimg = CIImage(image: img) else { return nil } let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]) guard let features = detector?.features(in: ciimg) else { return nil } guard let feature = features.first(where: { $0.type == CIFeatureTypeQRCode }) as? CIQRCodeFeature else { return nil } return feature.messageString // 识别结果 } /// 识别二维码和条形码 public static 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)") } }
要得到你必须要付出,要付出你还要学会坚持,如果你真的觉得很难,那你就放弃,但是你放弃了就不要抱怨,我觉得人生就是这样,世界真的是平等的,每个人都要通过自己的努力,去决定自己生活的样子。