Swift(十二):QRScanner 二维码封装总结

封装类 SQRCode.swift

//
//  SQRCode.swift 封装集成类
//  QRCode
//
//  Created by HMC on 16/8/16.
//  Copyright © 2016年 SKing. All rights reserved.
//

import UIKit
import AVFoundation

//闭包的别名
typealias result = (String)->()

class SQRCode: NSObject {
    
    //懒加载 闭包
    lazy var input : AVCaptureInput? = {
        
        //获取摄像头
        let hardWareDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
        
        //输入
        guard let input = try? AVCaptureDeviceInput(device: hardWareDevice) else{
            return nil
        }
        return input
        
    }()
    
    lazy var output : AVCaptureMetadataOutput? = {
        //输出
        let output = AVCaptureMetadataOutput()
        //设置输出的代理
        output.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        
        return output
    }()
    
    lazy var captureLayer : AVCaptureVideoPreviewLayer = {
        
        let captureLayer = AVCaptureVideoPreviewLayer(session: self.session)
        return captureLayer
        
    }()
    
    lazy var session : AVCaptureSession = {
        
        let session = AVCaptureSession()
        return session
    }()
    //结果闭包
    private var resultClosures : result?
    
    //单例
    static let sharedObject = SQRCode()
    
    /**
     实例方法:扫描二维码
     
     - parameter view:   在哪个 VC 的 View
     - parameter result: 闭包输出结果 便于回传到对应的 VC 上
     */
    func scanQRCode(view:UIView , result:(String)->()) {
        
        //
        resultClosures = result
        //连接输入输出
        
        if session.canAddInput(input) && session.canAddOutput(output) {
            session.addInput(input)
            session.addOutput(output)
        }
        
        //输出的二维码识别的码制(所有的码)
        output!.metadataObjectTypes = output!.availableMetadataObjectTypes
        
        
        //设置扫描的区域 0.0-1.0
        //        let screenBounds = UIScreen.mainScreen().bounds
        //        let x :CGFloat = scanBackground.frame.origin.x / screenBounds.size.width
        //        let y :CGFloat = scanBackground.frame.origin.y / screenBounds.size.height
        //        let width :CGFloat = scanBackground.frame.size.width / screenBounds.size.width
        //        let height :CGFloat = scanBackground.frame.size.height / screenBounds.size.height
        //        output.rectOfInterest = CGRectMake(y, x, height, width)
        
        //添加摄像头图层 (其实不是必须的) 防止重复
        let sublayers = view.layer.sublayers!
        guard !sublayers.contains(captureLayer)  else {
            
            return
        }
        
        captureLayer.frame = view.layer.bounds
        view.layer.insertSublayer(captureLayer, atIndex: 0)
        
        // 启动回话: 此时开始采集数据,输出对象
        session.startRunning()
        
        
    }
    
    
    
    /**
     类方法:生成二维码
     
     - parameter string:        字符串
     - parameter iconImageName: 中心的 Icon
     
     - returns: 生成的二维码
     */
    class func createQR(string : String?,iconImageName: String?) -> UIImage? {
        
        //创建二维码滤镜 固定格式 参数必须为 : CIQRCodeGenerator
        let filter = CIFilter(name: "CIQRCodeGenerator")
        
        //复位滤镜,以便下次使用
        filter?.setDefaults()
        
        //KVC 设置输入值  ps:key 固定为inputMessage ,value 必须为 nsdata 类型
        guard string != nil else {
            return nil
        }
        let inputData = string!.dataUsingEncoding(NSUTF8StringEncoding)
        filter?.setValue(inputData, forKey: "inputMessage")
        
        //设置纠错率 一般设置为M
        filter?.setValue("M", forKey: "inputCorrectionLevel")
        
        //接收滤镜返回的图片,由于太小 需要拉伸放大
        guard let image = filter?.outputImage else {
            
            return nil
        }
        //颜色滤镜
        let colorFilter = CIFilter(name: "CIFalseColor")
        colorFilter?.setDefaults()
        colorFilter?.setValue(image, forKey: "inputImage")
        //前景色
        colorFilter?.setValue(CIColor(red: 225/255.0, green: 77/255.0,blue: 0), forKey: "inputColor0")
        //背景色
        colorFilter?.setValue(CIColor(red: 1, green: 1,blue: 1), forKey: "inputColor1")
        
        guard let colorImage = colorFilter?.outputImage else{
            return nil
        }
        //放大25倍 重绘
        let matrix = CGAffineTransformMakeScale(25, 25)
        //将 CIImage 转换为 UIImage
        let QRImage = UIImage(CIImage:colorImage.imageByApplyingTransform(matrix))
        
        //判定 icon 是否为空
        guard iconImageName != nil else {
            
            return nil
        }
        
        //重新绘制中心小图
        if let iconImage = UIImage(named: iconImageName!)  {
            
            let rect = CGRectMake(0, 0, QRImage.size.width, QRImage.size.height)
            UIGraphicsBeginImageContext(rect.size)
            QRImage.drawInRect(rect)
            
            
            let iconSize = CGSizeMake(rect.size.width * 0.25, rect.size.height * 0.25)
            let x = (rect.width - iconSize.width ) * 0.5
            let y = (rect.height - iconSize.height ) * 0.5
            
            iconImage.drawInRect(CGRectMake(x,y,iconSize.width,iconSize.height))
            let resultImage = UIGraphicsGetImageFromCurrentImageContext()
            
            UIGraphicsEndImageContext()
            
            return resultImage
        }
        
        
        return QRImage
    }
    
    
    /**
     类方法:识别二维码
     
     - parameter image: 被识别的图片
     
     - returns: 返回识别的结果
     */
    class func detectorQRFromImage(image:UIImage) -> (String?) {
        //转换为 CIImage
        let ciImage = CIImage(image: image)
        
        //创建探测器
        let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy : CIDetectorAccuracyHigh])
        
        //返回结果
        let features = detector.featuresInImage(ciImage!)
        //遍历结果
        for feature in features {
            let qrcode = feature as! CIQRCodeFeature
            
            //print(qrcode.messageString)
            return qrcode.messageString
            
        }
        return nil
        
    }

}


// MARK: - AVCaptureMetadataOutputObjectsDelegate
extension SQRCode : AVCaptureMetadataOutputObjectsDelegate {
    
    func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {
        
        guard metadataObjects.count > 0 else{
            
            return
        }
        var resultStr : String?
        
        for obj in metadataObjects {
            guard obj.isKindOfClass(AVMetadataMachineReadableCodeObject) else{
                
                return
            }
            
            let tmpObj = obj as! AVMetadataMachineReadableCodeObject
            
            print(tmpObj.stringValue)
            //print(tmpObj.corners)
            resultStr = tmpObj.stringValue
            
        }
        
        guard (resultClosures != nil) else{
            
            return
        }
        guard resultStr != nil else{
            
            return
        }
        resultClosures!(resultStr!)
    }
}

调用的例子:

例一

//
//  scanQRViewController.swift
//  QRCode
//
//  Created by HMC on 16/8/15.
//  Copyright © 2016年 SKing. All rights reserved.
//

import UIKit
import AVFoundation

class scanQRViewController: UIViewController {
    
    //lazy var session = AVCaptureSession()
    
    /// 扫描网格 距离 框的底部的长度
    @IBOutlet weak var lineToBottom: NSLayoutConstraint!
    /// 扫描框和扫描线的背景 View
    @IBOutlet weak var scanBackground: UIView!
    //扫描框
    @IBOutlet weak var scanDeadLine: UIImageView!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
        //        startScan()
        
        SQRCode.sharedObject.scanQRCode(view) { (result:String) in
            
            let alert = UIAlertController(title: "识别结果", message: result, preferredStyle: .Alert)
            let action = UIAlertAction(title: "好", style: .Default, handler: { (action: UIAlertAction) in
                self.dismissViewControllerAnimated(true, completion: nil)
            })
            alert.addAction(action)
            
            self.presentViewController(alert, animated: true, completion: nil)
            
        }
    }
    override func viewDidAppear(animated: Bool) {
        
        super.viewDidAppear(animated)
        
        startAnimationOfLine()
        
    }
    
}


// MARK: - 有关的 UI 和动画
extension scanQRViewController{
    /**
     动画的设置
     */
    func startAnimationOfLine() {
        
        //初始化线的位置
        lineToBottom.constant = scanBackground.frame.height
        loadViewIfNeeded()
        
        //设置结束位置
        lineToBottom.constant = -scanBackground.frame.height
        
        //设置动画
        UIView.animateWithDuration(3, animations: {
            //设置重复
            UIView.setAnimationRepeatCount(MAXFLOAT)
            self.view.layoutIfNeeded()
            
        }) { (bool : Bool) in
            
            print("回扫")
            
            
        }
        
    }
    
    
}

例二

//
//  showQRController.swift
//  QRCode
//
//  Created by HMC on 16/8/11.
//  Copyright © 2016年 SKing. All rights reserved.
//

import UIKit
import CoreImage

class showQRController: UIViewController {
    
    @IBOutlet weak var QRImageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        QRImageView.image = SQRCode.createQR("香雨如酥贵如珠,万家未觉身却无。 一心只为他人事,浓绿艳妆为谁梳?", iconImageName: "123")

        
    }
}

例三

//
//  detectorViewController.swift
//  QRCode
//
//  Created by HMC on 16/8/12.
//  Copyright © 2016年 SKing. All rights reserved.
//

import UIKit

class detectorViewController: UIViewController {
    
    
    @IBOutlet weak var imageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 获得 image
        guard let image = imageView.image else{
            
            return
        }
        
        let returnStr = SQRCode.detectorQRFromImage(image)
        
        //alert 显示识别出的内容
        let alert = UIAlertController(title: "识别内容", message:returnStr, preferredStyle: .Alert)
        let action = UIAlertAction(title: "关闭", style: .Default, handler: { (action : UIAlertAction) in
            self.dismissViewControllerAnimated(true, completion: nil)
        })
        
        alert.addAction(action)
        presentViewController(alert, animated: true, completion: nil)
        
        
        
        
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值