Swift: 自定义原生扫描二维码

序言:扫描二维码用到了AVFoundation,而从照片中检测和提取二维码信息则用到CoreImage。

  • 先看下效果页面:
WechatIMG1.png
  • 源码示例地址:扫描二维码

  • 技术要点1: 建立CaptureSession并startRunning

    func setupCaptureSession() {
        
        captureDevice = AVCaptureDevice.default(for: AVMediaType.video)
        
        do {
            try captureInput = AVCaptureDeviceInput.init(device: captureDevice!)
        }catch {
            
        }
        
        mataOutput = AVCaptureMetadataOutput.init()
        mataOutput?.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        
        captureSession = AVCaptureSession.init()
        
        if ((captureSession?.canAddInput(captureInput!))!) {
            captureSession?.addInput(captureInput!)
        }
        
        if ((captureSession?.canAddOutput(mataOutput!))!) {
            captureSession?.addOutput(mataOutput!)
        }
        
        if ((captureSession?.canSetSessionPreset(AVCaptureSession.Preset.high))!) {
            captureSession?.sessionPreset = .high
        }
        
        mataOutput?.metadataObjectTypes = [AVMetadataObject.ObjectType.qr]
        
        capturePreView = AVCaptureVideoPreviewLayer.init(session: captureSession!)
        
        capturePreView?.frame = self.view.frame
        self.view.layer.insertSublayer(capturePreView!, at: 0)
        
        captureSession?.startRunning()
        
        let rect = capturePreView!.metadataOutputRectConverted(fromLayerRect: self.interestRect)
        
        mataOutput?.rectOfInterest = rect
        
    }

需要重点提到的一个坑是:

在这行代码前面【 let rect = capturePreView!.metadataOutputRectConverted(fromLayerRect: self.interestRect)】
一定要先执行【
captureSession?.startRunning()】
否则【metadataOutputRectConverted返回的rect是{0,0,0,0}】,这样就没办法捕捉到二维码信息了

  • 技术要点2: 运用CIDetector进行检测照片中的二维码信息
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true) {
            let img = info[UIImagePickerController.InfoKey.originalImage] as! UIImage
            let decteor = CIDetector.init(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
            //let ciimg = img.ciImage
            //let ciimg = CIImage.init(image: img)
            //let ciimg = CIImage.init(data: img.pngData()!)
            let ciimg = CIImage.init(cgImage: img.cgImage!)
            let fetures = decteor?.features(in: ciimg)
            if (fetures?.count)! > 0 {
                if let qrFeture = fetures?.first as? CIQRCodeFeature {
                    self.endScan()
                    if (self.resultDelegate != nil) {
                        self.resultDelegate?.tt_handleQRScanResult(result: qrFeture.messageString!)
                    }
                    self.navigationController?.popViewController(animated: true)
                }
            }else {
                print("没有二维码信息")
            }
        }
    }
  • 技术要点3: 控制设备手电筒torch
 @objc func openLamp(_ sender: UIButton) {
        if ((captureDevice?.hasTorch)!) {
            if (!torchTag) {
                try? captureDevice?.lockForConfiguration()
                try? captureDevice?.setTorchModeOn(level: 0.6)
                captureDevice?.unlockForConfiguration()
                torchTag = true
            }else {
                try? captureDevice?.lockForConfiguration()
                captureDevice?.torchMode = .off
                captureDevice?.unlockForConfiguration()
                torchTag = false
            }
        }
    }

你可能感兴趣的:(Swift: 自定义原生扫描二维码)