swift 二维码识别的实现

来源:互联网 发布:中文手写软件下载 编辑:程序博客网 时间:2024/05/22 00:59

本文是用系统的AVFoundation来实现二维码的扫描(注意:只支持真机)

代码地址

https://github.com/jinliyuelong/LYJSwiftDemo

1.创建viewcontroller来显示按钮进行进入扫描窗口


import UIKitimport AVFoundationclass QRcodeViewController: UIViewController {        override func viewDidLoad() {        super.viewDidLoad()                self.setupUi()    }                override func didReceiveMemoryWarning() {        super.didReceiveMemoryWarning()        // Dispose of any resources that can be recreated.    }        func setupUi()  {        self.view.backgroundColor = UIColor.white                        let button = UIButton(frame: CGRect(x: (UIScreen.main.bounds.size.width-100) * 0.5, y: (UIScreen.main.bounds.size.height-30) * 0.5, width: 100, height: 30))                button.setTitle("扫一扫", for: UIControlState())                button.setTitleColor(UIColor.blue, for: UIControlState())                button.addTarget(self, action: #selector(QRcodeViewController.buttonAction(_:)), for: UIControlEvents.touchUpInside)                self.view.addSubview(button)            }        func buttonAction(_ sender : AnyObject){        print("扫一扫")                if self.cameraPermissions() {                let  scanner = ScannerViewController()        self.navigationController?.pushViewController(scanner, animated: true)        }else{                    self.displayAlertControllerWithMessage("当前设备没有相机权限")        }                    }                /**     判断相机权限          - returns: 有权限返回true,没权限返回false     */    func cameraPermissions() -> Bool{                let authStatus:AVAuthorizationStatus = AVCaptureDevice.authorizationStatus(forMediaType: AVMediaTypeVideo)                debugPrint("当前的权限是=====\(authStatus.rawValue)")                if(authStatus == AVAuthorizationStatus.authorized || authStatus == AVAuthorizationStatus.notDetermined) {            return true        }else {            return false        }            }                }
2.创建扫描viewcontroller


里面有一个用来显示组件的view:ScannerBackgroundView和controller

import UIKitclass ScannerBackgroundView: UIView {            var scanResult = UITextField()        var scanResultPlaceHolder:String = ""                    //屏幕扫描区域视图    let barcodeView = UIView(frame: CGRect(x: screenWidth  * 0.2, y:  screenHeight * 0.15, width: screenWidth  * 0.6, height: screenWidth  * 0.6))    //扫描线    let scanLine = UIImageView()        var timer = Timer()        override init(frame: CGRect) {        super.init(frame: frame)            }            func stopScan()  {        timer.invalidate()    }                init(frame: CGRect, scanResultPlaceHolder:String) {                super.init(frame: frame)                self.scanResultPlaceHolder = scanResultPlaceHolder                self.setupUi()    }            func setupUi()  {        barcodeView.layer.borderWidth = 1.0        barcodeView.layer.borderColor = UIColor.white.cgColor        self.addSubview(barcodeView)                //设置扫描线        scanLine.frame = CGRect(x: 0, y: 0, width: barcodeView.frame.size.width, height: 5)        scanLine.image = UIImage(named: "QRCodeScanLine")                //添加扫描线图层        barcodeView.addSubview(scanLine)                self.createBackGroundView()                        timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(moveScannerLayer(_:)), userInfo: nil, repeats: true)                    }            func  createBackGroundView() {        let topView = UIView(frame: CGRect(x: 0, y: 0,  width: screenWidth , height:  screenHeight * 0.15))        let bottomView = UIView(frame: CGRect(x: 0, y: screenWidth  * 0.6 +  screenHeight * 0.15, width: screenWidth , height:  screenHeight * 0.85 - screenWidth * 0.6))                let leftView = UIView(frame: CGRect(x: 0, y:  screenHeight * 0.15, width: screenWidth  * 0.2, height: screenWidth  * 0.6))        let rightView = UIView(frame: CGRect(x: screenWidth  * 0.8, y:  screenHeight * 0.15, width: screenWidth  * 0.2, height: screenWidth  * 0.6))                topView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.4)        bottomView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.4)        leftView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.4)        rightView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.4)                let label = UILabel(frame: CGRect(x: 0, y: 10, width: screenWidth , height: 21))        label.textAlignment = .center        label.font = UIFont.systemFont(ofSize: 14)        label.textColor = UIColor.white        label.text = "将二维码/条形码放入扫描框内,即自动扫描"                bottomView.addSubview(label)                bottomView.addSubview(scanResult)                        self.addscanResult()                self.addSubview(topView)        self.addSubview(bottomView)        self.addSubview(leftView)        self.addSubview(rightView)                            }            func addscanResult()  {                self.scanResultP()        self.scanResultF()    }            //设置reslut    func scanResultP()  {                scanResult.textAlignment = .left                scanResult.textColor = UIColor.white                scanResult.layer.masksToBounds = true                scanResult.layer.borderColor = mygrayColor.cgColor                scanResult.layer.borderWidth = 1                scanResult.leftViewMode = .always                        scanResult.attributedPlaceholder = NSAttributedString(string: self.scanResultPlaceHolder, attributes: [NSForegroundColorAttributeName:UIColor.white ])                scanResult.layer.cornerRadius = 3                scanResult.font = UIFont.systemFont(ofSize: CGFloat(mylableSize))                    }        func scanResultF()  {                scanResult.frame = CGRect.init(x: screenWidth * 0.1, y: 10 + screenHeight * 0.1, width: screenWidth * 0.8, height: 40)            }                func scanResultD(reslut:String){                scanResult.text = " " + reslut                    }            required init?(coder aDecoder: NSCoder) {        fatalError("init(coder:) has not been implemented")    }                    //让扫描线滚动    func moveScannerLayer(_ timer : Timer) {        scanLine.frame = CGRect(x: 0, y: 0, width: self.barcodeView.frame.size.width, height: 12);        UIView.animate(withDuration: 2) {            self.scanLine.frame = CGRect(x: self.scanLine.frame.origin.x, y: self.scanLine.frame.origin.y + self.barcodeView.frame.size.height - 10, width: self.scanLine.frame.size.width, height: self.scanLine.frame.size.height);                    }            }}
controller为:

import AVFoundationimport UIKitimport Photosclass ScannerViewController: UIViewController,AVCaptureMetadataOutputObjectsDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate {        //相机显示视图    let cameraView = ScannerBackgroundView(frame: UIScreen.main.bounds ,scanResultPlaceHolder:"请输入扫描设备")            let captureSession = AVCaptureSession()        override func viewDidLoad() {        super.viewDidLoad()        self.view.backgroundColor = UIColor.black        //失效相册        //设置导航栏                let barButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.add, target: self, action: #selector(ScannerViewController.selectPhotoFormPhotoLibrary(_:)))                self.navigationItem.rightBarButtonItem = barButtonItem                //        self.view.addSubview(cameraView)                //初始化捕捉设备(AVCaptureDevice),类型AVMdeiaTypeVideo        let captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)                let input :AVCaptureDeviceInput                //创建媒体数据输出流        let output = AVCaptureMetadataOutput()                //捕捉异常        do{            debugPrint("进入do循环")            //创建输入流            input = try AVCaptureDeviceInput(device: captureDevice)                        //把输入流添加到会话            captureSession.addInput(input)                        //把输出流添加到会话            captureSession.addOutput(output)        }catch {            print("异常")        }                //创建串行队列        let dispatchQueue = DispatchQueue(label: "queue", attributes: [])                //设置输出流的代理        output.setMetadataObjectsDelegate(self, queue: dispatchQueue)                //设置输出媒体的数据类型        output.metadataObjectTypes = NSArray(array: [AVMetadataObjectTypeQRCode,AVMetadataObjectTypeEAN13Code,AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeCode128Code]) as [AnyObject]                //创建预览图层        let videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)                //设置预览图层的填充方式        videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill                //设置预览图层的frame        videoPreviewLayer?.frame = cameraView.bounds                //将预览图层添加到预览视图上        cameraView.layer.insertSublayer(videoPreviewLayer!, at: 0)                //设置扫描范围        output.rectOfInterest = CGRect(x: 0.2, y: 0.15, width: 0.6, height: 0.6)            }        override func viewWillAppear(_ animated: Bool) {        super.viewWillAppear(animated)        self.tabBarController?.tabBar.isHidden = true        self.scannerStart()    }        func scannerStart(){        captureSession.startRunning()        debugPrint("开始扫描")            }        func scannerStop() {        captureSession.stopRunning()        debugPrint("结束扫描")                cameraView.stopScan()    }                //扫描代理方法    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {        if metadataObjects != nil && metadataObjects.count > 0 {            let metaData = metadataObjects.first                        debugPrint("进入代理方法")                        debugPrint("扫描结果是=======\((metaData as AnyObject).stringValue ?? " ")")            //            print((metaData as AnyObject).stringValue ?? " ")            DispatchQueue.main.async(execute: {                let result:String = (metaData as AnyObject).stringValue ?? " "                                self.cameraView.scanResultD(reslut: result)                                self.cameraView.isUserInteractionEnabled = false                            })                        self.scannerStop()                        //            captureSession.stopRunning()        }                    }                //从相册中选择图片    func selectPhotoFormPhotoLibrary(_ sender : AnyObject){                if self.PhotoLibraryPermissions(){            let picture = UIImagePickerController()            picture.sourceType = UIImagePickerControllerSourceType.photoLibrary            picture.delegate = self            self.present(picture, animated: true, completion: nil)                                }else{                                    self.displayAlertControllerWithMessage("该设备没有相册权限")        }                    }        //选择相册中的图片完成,进行获取二维码信息        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {                let image = info[UIImagePickerControllerOriginalImage]                let imageData = UIImagePNGRepresentation(image as! UIImage)                let ciImage = CIImage(data: imageData!)                let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyLow])                let array = detector?.features(in: ciImage!)                let result : CIQRCodeFeature = array!.first as! CIQRCodeFeature                        debugPrint("扫描结果是=======\((result.messageString))")                        let resultView = WebViewController()        resultView.url = result.messageString                self.navigationController?.pushViewController(resultView, animated: true)        picker.dismiss(animated: true, completion: nil)        print(result.messageString ?? "错误信息")    }                           /**     判断相册权限          - returns: 有权限返回ture, 没权限返回false     */        func PhotoLibraryPermissions() -> Bool {                                let library:PHAuthorizationStatus = PHPhotoLibrary.authorizationStatus()                if(library == PHAuthorizationStatus.denied || library == PHAuthorizationStatus.restricted){            return false        }else {            return true        }            }    }

运行效果为



注意事项:代码需要引入我写的一个扩展和工具文件

 UIColor+Extension

////  UIColor+Extension.swift//  MyswiftDemo////  Created by Liyanjun on 2017/1/14.//  Copyright © 2017年 hand. All rights reserved.//import UIKitimport Foundationextension UIColor {        /**     Convenient initializer for RGB color code with default alpha 1.0          - Parameters:     - red: The integer code for red     - green: The integer code for green     - blue: The integer code for blue     */    convenience init(red: Int, green: Int, blue: Int) {        assert(red >= 0 && red <= 255, "Invalid red component")        assert(green >= 0 && green <= 255, "Invalid green component")        assert(blue >= 0 && blue <= 255, "Invalid blue component")                self.init(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: 1.0)    }        /**     Convenient initializer for pure hex color code          - Parameter hex: The hex code of color     */    convenience init(hex: Int) {        self.init(red: (hex >> 16) & 0xff, green: (hex >> 8) & 0xff, blue: hex & 0xff)    }        static let system = UIColor(hex: 0x035d9a)    static let background = UIColor(hex: 0xf4f5f7)    static let systemGray = UIColor(hex: 0xe2e2e2)        }
和工具文件
////  LYJPch.swift//  Colliers-CFIM////  Created by Liyanjun on 2017/1/14.//  Copyright © 2017年 hand. All rights reserved.//import UIKitimport SnapKitlet myBlackColr = UIColor(hex: 0x424243)//常用的黑色let mygrayColor = UIColor(hex: 0xb2b2b2)//常用的灰色let TitlelableColor =  myBlackColr//系统常用的黑色//常用字体大小let mylableSize = 15//设置常用字体大小为16let mycommonEdge:CGFloat = 13//上下左右编剧let commonCellHeight = CGFloat(37.0 + 6)//常用tableCell的高度var keyWindow: UIWindow? {    return UIApplication.shared.keyWindow}var isChinese: Bool {    if let code = NSLocale.preferredLanguages.first, code.hasPrefix("zh") {        return true    }    return false}var screenWidth:CGFloat {    return UIScreen.main.bounds.width}var screenHeight:CGFloat {    return UIScreen.main.bounds.height}




AVFoundation



1 0
原创粉丝点击