【Swift】原生二维码扫描

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Emperor_huanzi/article/details/79578542
import UIKit
import AVFoundation
protocol ScanViewDelegate: NSObjectProtocol{
    /// 扫码数据
    ///
    /// - Parameter pileCode: 编码
    func captureOutputSuccess(pileCode:String);
}
class ScanView: UIView,AVCaptureMetadataOutputObjectsDelegate {
    /// 创建设备
    var captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
    /// 捕获视频
    var captureSession : AVCaptureSession?
    /// 捕获视频的预览层
    var videoPreviewLayer : AVCaptureVideoPreviewLayer?

    /// 提示文字
    var titleLabel = UILabel()
    /// 图片
    var quJingImage:UIImageView!
    var saoMaTiaoImage : UIImageView?
    /// 开灯
    var openLampButton:UIButton!
    // 代理
    weak var delegate : ScanViewDelegate!

    /// 元数据输出
    let captureMetadataOutput = AVCaptureMetadataOutput()
    override init(frame: CGRect) {
        super.init(frame: frame)


        createQrView()
        createScanPanelView()
    }
    /// 创建扫描设备
    func createQrView(){
        let authStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)
        if authStatus == AVAuthorizationStatus.restricted || authStatus == AVAuthorizationStatus.denied {
            DZAlertView.sharedInstance.show(DZAlertViewType.blackViewAndClickDisappear, contentType: DZAlertContentViewType.warning, message: ["请在iPhone的“设置”-“隐私”-“相机”功能中,找到“\(Bundle.main.appDisplayName)”打开相机访问权限"])
            return
        }

        //给设备添加input输入
        var input : AnyObject!
        do{
            input = try AVCaptureDeviceInput(device: captureDevice)
        }catch{

        }
        if input == nil {
            return
        }
        captureSession = AVCaptureSession()
        captureSession?.addInput(input as! AVCaptureInput)


        captureSession?.addOutput(captureMetadataOutput)
        captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        captureMetadataOutput.metadataObjectTypes = [AVMetadataObjectTypeQRCode]

        /// 显示的layer
        videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
       let isphone = UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.phone ? true : false
        if isphone {
            videoPreviewLayer?.connection.videoOrientation = AVCaptureVideoOrientation.portrait
        }else{
            videoPreviewLayer?.connection.videoOrientation = AVCaptureVideoOrientation.landscapeRight
        }

        videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
        videoPreviewLayer?.frame = self.layer.bounds
        self.layer.addSublayer(videoPreviewLayer!)
        captureSession?.startRunning()

    }

    /// 创建扫描面板
    func createScanPanelView(){
        //提示文字
        self.addSubview(titleLabel)
        titleLabel.snp.makeConstraints { (make) -> Void in
            make.top.equalTo(UIConfigure.Width / 750 * 45)
            make.left.equalTo(40)
            make.right.equalTo(-40)
        }
        titleLabel.numberOfLines = 0
        titleLabel.textAlignment = NSTextAlignment.center
        titleLabel.text = "将二维码放入框中即可自动扫描"
        titleLabel.textColor = UIColor.white
        titleLabel.font = UIConfigure.Font14

        // 取景框图片
        quJingImage = UIImageView(image: BaseImage(named: "QSD_Scan_ScanQr")?.image)
        self.addSubview(quJingImage)
        quJingImage.snp.makeConstraints { (make) -> Void in
            make.top.equalTo(titleLabel.snp.bottom).offset(UIConfigure.Width / 750 * 30 * UIConfigure.SizeScale)
            make.centerX.equalTo(self.snp.centerX)
            make.width.equalTo(220 * UIConfigure.SizeScale)
            make.height.equalTo(220 * UIConfigure.SizeScale)
        }
        self.layoutIfNeeded()
        print(CGRect(x: quJingImage.frame.origin.x / UIConfigure.Width, y: quJingImage.frame.origin.y / (UIConfigure.Height - 64), width: quJingImage.frame.size.width / UIConfigure.Width, height: quJingImage.frame.size.height / (UIConfigure.Height - 64)))

//        captureMetadataOutput.rectOfInterest = CGRect(x: quJingImage.frame.origin.x / UIConfigure.Height, y: quJingImage.frame.origin.y / UIConfigure.Width, width: quJingImage.frame.size.width / UIConfigure.Width, height: quJingImage.frame.size.height / UIConfigure.Width)

        // 上下左右四个遮盖黑边
        let topView = UIView()
        self.addSubview(topView)
        topView.snp.makeConstraints { (make) -> Void in
            make.top.equalTo(0)
            make.left.equalTo(0)
            make.right.equalTo(0)
            make.bottom.equalTo(quJingImage.snp.top)
        }
        topView.backgroundColor = UIColor.black
        topView.alpha = 0.3

        let leftView = UIView()
        self.addSubview(leftView)
        leftView.snp.makeConstraints { (make) -> Void in
            make.top.equalTo(topView.snp.bottom)
            make.left.equalTo(0)
            make.right.equalTo(quJingImage.snp.left)
            make.bottom.equalTo(0)
        }
        leftView.backgroundColor = UIColor.black
        leftView.alpha = 0.3

        let rightView = UIView()
        self.addSubview(rightView)
        rightView.snp.makeConstraints { (make) -> Void in
            make.top.equalTo(topView.snp.bottom)
            make.left.equalTo(quJingImage.snp.right)
            make.right.equalTo(0)
            make.bottom.equalTo(0)
        }
        rightView.backgroundColor = UIColor.black
        rightView.alpha = 0.3

        let bottomView = UIView()
        self.addSubview(bottomView)
        bottomView.snp.makeConstraints { (make) -> Void in
            make.top.equalTo(quJingImage.snp.bottom)
            make.left.equalTo(leftView.snp.right)
            make.right.equalTo(rightView.snp.left)
            make.bottom.equalTo(0)
        }
        bottomView.backgroundColor = UIColor.black
        bottomView.alpha = 0.3

        self.bringSubview(toFront: titleLabel)
        //扫描条不断动的那个
        saoMaTiaoImage = UIImageView(image: BaseImage(named: "QSD_Scan_ScanQrLIne")?.image)
        self.addSubview(saoMaTiaoImage!)
        saoMaTiaoImage!.snp.makeConstraints { (make) -> Void in
            make.top.equalTo(quJingImage.snp.top)
            make.centerX.equalTo(quJingImage.snp.centerX)
            make.width.equalTo(200 * UIConfigure.SizeScale)
            make.height.equalTo(1)
        }
        saoMaTiaoImage?.isHidden = false

        changeStyle()

        //闪光灯按钮
        openLampButton = UIButton()
        self.addSubview(openLampButton)
        openLampButton.snp.makeConstraints { (make) -> Void in
            make.top.equalTo(quJingImage.snp.bottom).offset(UIConfigure.Width / 750 * 15 * UIConfigure.SizeScale)
            make.left.equalTo(quJingImage.snp.left)
            make.right.equalTo(quJingImage.snp.right)
            make.height.equalTo(UIConfigure.SimallButtonHeight)
        }
        openLampButton.setTitle("开灯", for: UIControlState.normal)
        openLampButton.setTitle("关灯", for: UIControlState.selected)
        openLampButton.addTarget(self, action: #selector(ScanView.openShanGuang(sender:)), for: UIControlEvents.touchUpInside)
        openLampButton.setTitleColor(UIConfigure.ThemeColor, for: UIControlState.normal)
        openLampButton.titleLabel?.textColor = UIConfigure.ThemeColor
        openLampButton.backgroundColor = UIColor.white
        openLampButton.layer.cornerRadius = UIConfigure.CornerRadius
        openLampButton.layer.masksToBounds = true
        openLampButton.layer.borderColor = UIConfigure.ThemeColor.cgColor
        openLampButton.layer.borderWidth = 0.5
    }

    /**
     扫描条不断的移动
     */
    func changeStyle(){
        guard self.saoMaTiaoImage != nil else {
            return
        }
        self.saoMaTiaoImage?.isHidden  = false
        UIView.animate(withDuration: 3.5, animations: { [weak self] () -> Void in
            if(self != nil){
                self!.saoMaTiaoImage?.transform = CGAffineTransform(translationX: 0, y: 220 * UIConfigure.SizeScale)
            }
        }) { [weak self](end) -> Void in
            if(self != nil){
                UIView.animate(withDuration: 3.5, animations: { [weak self] in
                    if(self != nil){
                        self!.saoMaTiaoImage?.transform = CGAffineTransform.identity
                    }
                }, completion: { [weak self](end) in
                    if self != nil {
                        self!.changeStyle()
                    }
                })
            }
        }
    }

    /// 开闪光
    func openShanGuang(sender:UIButton){
        sender.isSelected = !sender.isSelected
        if captureDevice != nil && captureDevice!.hasFlash && captureDevice!.hasTorch {
            do {
                try captureDevice?.lockForConfiguration()
                if sender.isSelected {
                    captureDevice!.flashMode = AVCaptureFlashMode.on
                    captureDevice!.torchMode = AVCaptureTorchMode.on
                }else{
                    captureDevice!.flashMode = AVCaptureFlashMode.off
                    captureDevice!.torchMode = AVCaptureTorchMode.off

                }

                captureDevice?.unlockForConfiguration()
            }catch{

            }
        }else{
            DZAlertView.sharedInstance.show(DZAlertViewType.blackViewAndClickDisappear, contentType: DZAlertContentViewType.warning, message: ["不能打开设备的闪光灯"])
        }
    }


    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
        if metadataObjects == nil || metadataObjects.count == 0 {
            return
        }

        playSoundEffect(name: "Qcodesound.caf")
        let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
        if metadataObj.type == AVMetadataObjectTypeQRCode {
            if metadataObj.stringValue != nil {
                captureSession?.stopRunning()
                print("刚刚扫描出来!!!\(metadataObj.stringValue)")
                delegate.captureOutputSuccess(pileCode: metadataObj.stringValue!)
            }
        }

    }


    /// 扫描成功后播放声音
    ///
    /// - Parameter name: 地址
    func playSoundEffect(name : String){
        let audioFile = Bundle.main.path(forResource: name, ofType: nil)
        let fileUrl = URL(fileURLWithPath: audioFile!)
        var soundID : SystemSoundID = 0

        AudioServicesCreateSystemSoundID(fileUrl as CFURL, &soundID)
        AudioServicesAddSystemSoundCompletion(soundID, nil, nil, { (SounID, clientData) in
            print("播放完成")
        }, nil)

        AudioServicesPlaySystemSound(soundID)
    }

    deinit {
        print("扫描销毁")
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

猜你喜欢

转载自blog.csdn.net/Emperor_huanzi/article/details/79578542
今日推荐