swift 扫描二维码 稳定快速准确各大APP均需要

 
//  ScanViewController.swift
 
//  Created by sts  on 2019/6/20.
 



import UIKit

import AVFoundation

class ScanViewController: UIViewController,AVCaptureMetadataOutputObjectsDelegate {
 
    //是否是第一次扫描到结果

    var firstResult: Bool = true

    

    //AVCaptureSession对象来执行输入设备和输出设备之间的数据传递

    var session: AVCaptureSession?

    //输入设备

    var videoInput: AVCaptureDeviceInput?

    //输出对象

    var metadataOutput: AVCaptureMetadataOutput = AVCaptureMetadataOutput()

    //预览图层

    var previewLayer: AVCaptureVideoPreviewLayer?

    

    var scanTimer: Timer?

    

    //边框

    lazy var borderView: UIImageView = UIImageView(image: UIImage(named:"ty_qrcode_bg"))

    //line

    lazy var scanLineView: UIImageView = UIImageView(image: UIImage(named: "ty_qrcode_line"))

    

    private let borderWidth:CGFloat =   400

    private let topMargin: CGFloat =  230

    override func viewDidLoad() {

        super.viewDidLoad()

        if(!checkCameraAuth()){

            let alertController = UIAlertController(title: nil,message: "请在iphone的“设置-隐私-相机”选项中,允许应用访问你的相机", preferredStyle: .alert)

            let cancelAction = UIAlertAction(title: "取消", style: .cancel, handler: {

                action in

                self.navigationController?.popViewController(animated: true)

            })

            let okAction = UIAlertAction(title: "前往", style: .default, handler: {

                action in

                let settingUrl = NSURL(string: UIApplication.openSettingsURLString)!

                if UIApplication.shared.canOpenURL(settingUrl as URL)

                {

                    UIApplication.shared.openURL(settingUrl as URL)

                }

            })

            alertController.addAction(cancelAction)

            alertController.addAction(okAction)

            self.present(alertController, animated: true, completion: nil)

        }

        setupCaptureSession()

        addSubviews()

        

        scanTimer = Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(startAnimation), userInfo: nil, repeats: true)



    }

    override func viewWillAppear(_ animated: Bool) {

        firstResult = true

        if let session = self.session {

            session.startRunning()

        }

        scanTimer?.fireDate = NSDate.distantPast

    }

    

    func checkCameraAuth() -> Bool {

        let status = AVCaptureDevice.authorizationStatus(for: .video)

        var  b =  status == .authorized

        return  b;

    }

    

    //MARK:生成背景遮盖

    func getCoverView(left: CGFloat, top: CGFloat) -> UIImage? {

        UIGraphicsBeginImageContext(CGSize(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height - 64))

        let contextRef = UIGraphicsGetCurrentContext()

        contextRef?.setFillColor(UIColor (red: 111/255.0, green: 111/255.0, blue: 22/255.0, alpha: 0.5).cgColor)

        contextRef?.fill(CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))

        let inset:CGFloat =   4

        contextRef?.clear(CGRect(x: left + inset, y: top + inset, width: UIScreen.main.bounds.size.width - left * 2 - inset * 2, height: UIScreen.main.bounds.size.width - left * 2 - inset * 2))

        return UIGraphicsGetImageFromCurrentImageContext()

    }

    func addSubviews() {

        let leftMargin: CGFloat = (UIScreen.main.bounds.size.width - borderWidth) * 0.5

//

//        let coverImageView = UIImageView(frame: CGRect(x: 0, y: 64, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height - 64))

//        coverImageView.backgroundColor = UIColor.clear

//        coverImageView.image = self.getCoverView(left: leftMargin, top: topMargin)

//        view.addSubview(coverImageView)

        

        //扫描边框

        borderView.frame = CGRect.init(x: (UIScreen.main.bounds.size.width-(self.view.center.x+30))/2, y: (UIScreen.main.bounds.size.height-(self.view.center.x + 30))/2, width: self.view.center.x + 30, height: self.view.center.x + 30)

        view.addSubview(borderView)

        

        //扫描的线

        scanLineView.frame = CGRect(x:borderView.frame.origin.x+2, y:   borderView.frame.origin.y+2, width: borderView.bounds.size.width, height: 2)

        view.addSubview(scanLineView)

        print(borderView.frame.origin.x)

        print(scanLineView.frame)

        print(borderView.frame)

        var tipLabel = UILabel.init();

//        let tipLabel = UILabel.createLabelWith(title: "将取景框对准二维码,即可自动扫描", titleColor: UIColor.white, fontSize: 24, alignment: .center, lines: 0)

        tipLabel.text = "对准二维码,即可自动扫描";

        tipLabel.textColor = UIColor.white;

        tipLabel.font = UIFont.systemFont(ofSize: 14)

        tipLabel.textAlignment = .center;

        tipLabel.frame = CGRect(x: 0, y:0, width:200, height: 40)

        tipLabel.center = CGPoint(x: borderView.center.x , y: borderView.center.y + (self.view.center.x + 30)/2 + 30);

        view.addSubview(tipLabel)

    }

    

    //MARK:- 开始扫描动画

    @objc func startAnimation() -> Void {

        

        //让约束从顶部开始

        var frame = self.scanLineView.frame

        frame.origin.y = borderView.frame.origin.y

        self.scanLineView.frame = frame

        self.scanLineView.layoutIfNeeded()



        UIView.animate(withDuration: 3.0, animations: {

            //改变frame

            frame.origin.y = self.borderView.frame.origin.y+self.borderView.bounds.size.height

            self.scanLineView.frame = frame

            //强制更新界面

            self.scanLineView.layoutIfNeeded()

        })

    }

    

    func stopAnimation() -> Void {

        //让约束从顶部开始

        var frame = self.scanLineView.frame

        frame.origin.y = 64 + topMargin

        self.scanLineView.frame = frame

        self.scanLineView.layoutIfNeeded()

        

        scanTimer?.invalidate()

        scanTimer = nil

    }

    override func viewWillDisappear(_ animated: Bool) {

        super.viewWillDisappear(animated)

        //关闭session

        if let session = self.session{

            session.stopRunning()

        }

        

    }

    

    deinit {

        scanTimer?.invalidate()

        scanTimer = nil

        print("scan-----deinit")

    }

    //MARK:设置session

    func setupCaptureSession() {

        

        self.session = AVCaptureSession()

        

        //高质量采集率

        self.session?.sessionPreset = AVCaptureSession.Preset.high

        

        guard let device = AVCaptureDevice.default(for: AVMediaType.video) else { return }

        

        //更改这个设置的时候必须先锁定设备,修改完后再解锁,否则崩溃

        do{

            try device.lockForConfiguration()

            //设置闪光灯为自动

            device.flashMode = AVCaptureDevice.FlashMode.auto

            device.unlockForConfiguration()

        }catch{

            print("崩溃")

        }

        

        do{

            try self.videoInput = AVCaptureDeviceInput(device: device)

        }catch{

            print("崩溃")

        }

        

        //输入设备

        if let videoInput = self.videoInput {

            

            if self.session?.canAddInput(videoInput) == true {

                self.session?.addInput(videoInput)

            }

        }

        

        //添加输出

        if self.session?.canAddOutput(self.metadataOutput) == true{

            self.session?.addOutput(self.metadataOutput)

        }

        

        self.metadataOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.qr,

                                                   AVMetadataObject.ObjectType.ean13,

                                                   AVMetadataObject.ObjectType.ean8,

                                                   AVMetadataObject.ObjectType.code128,

                                                   AVMetadataObject.ObjectType.code39,

                                                   AVMetadataObject.ObjectType.code93]

        

        self.metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)

        

        

        //预览图层

        if let session = self.session {

            self.previewLayer = AVCaptureVideoPreviewLayer(session: session)

            self.previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill

            self.previewLayer?.frame = CGRect(x: 0, y : 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height)

        }

        

        if let layer = self.previewLayer {

            view.layer.insertSublayer(layer, at: 0)

        }

    }

    

    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {

        self.session?.stopRunning();

        if (metadataObjects.count >= 1) {

            //数组中包含的都是AVMetadataMachineReadableCodeObject 类型的对象,该对象中包含解码后的数据

            var qrObject:AVMetadataMachineReadableCodeObject = metadataObjects.last as! AVMetadataMachineReadableCodeObject;

            //拿到扫描内容在这里进行个性化处理

            var result = qrObject.stringValue;

            print("result"+result!)

            //解析数据进行处理并实现相应的逻辑

            //代码省略

        }

        

    }

    /*

    // MARK: - Navigation



    // In a storyboard-based application, you will often want to do a little preparation before navigation

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        // Get the new view controller using segue.destination.

        // Pass the selected object to the new view controller.

    }

    */



}

 

 

 

 

 

 

 

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值