二维码系列(五)综合DEMO演练,工具类效能提升
来源:互联网 发布:邵阳学院教务网络系统 编辑:程序博客网 时间:2024/05/29 14:46
https://github.com/targetcloud/QRToolDemo
上面是Github地址,读者可以自己下载下来观摩(欢迎STAR)
本文是对整个二维码系列的综合,读者若没有时间细究功能实现,可直接用本DEMO代码调用示例使用即可
首先是QRTool工具类(有升级,更加稳固),拖到你的工程中去
//// QRTool.swift//// Created by targetcloud on 2016/12/4.// Copyright © 2016年 targetcloud. All rights reserved.// http://blog.csdn.net/callzjyimport UIKitimport AVFoundationtypealias ScanResultBlock = ([String]) -> ()class QRTool: NSObject { static let shareInstance = QRTool() private lazy var input: AVCaptureDeviceInput? = { let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) var input: AVCaptureDeviceInput? do { input = try AVCaptureDeviceInput(device: device) return input }catch { return nil } }() private lazy var output: AVCaptureMetadataOutput = { let output = AVCaptureMetadataOutput() output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main) return output }() lazy var session: AVCaptureSession = AVCaptureSession() lazy var previewLayer: AVCaptureVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: self.session) fileprivate var scanResultBlock: ScanResultBlock? fileprivate var isDrawFrame: Bool = false fileprivate var drawLindWidth:CGFloat = 1 fileprivate var drawStrokeColor:UIColor = UIColor.red func scanQRCode(_ inView: UIView, isDrawFrame: Bool = true,drawStrokeColor:UIColor = UIColor.red,drawLindWidth:CGFloat = 5, resultBlock: @escaping (_ resultStrs: [String])->()) { scanResultBlock = resultBlock self.isDrawFrame = isDrawFrame self.drawStrokeColor = drawStrokeColor self.drawLindWidth = drawLindWidth if session.inputs.count==0 && session.outputs.count==0{ if session.canAddInput(input) && session.canAddOutput(output) { session.addInput(input) session.addOutput(output) }else { return } } output.metadataObjectTypes = [AVMetadataObjectTypeQRCode] if inView.layer.sublayers == nil { previewLayer.frame = inView.layer.bounds inView.layer.insertSublayer(previewLayer, at: 0) }else { let subLayers = inView.layer.sublayers! if !subLayers.contains(previewLayer) { previewLayer.frame = inView.layer.bounds inView.layer.insertSublayer(previewLayer, at: 0) } } session.startRunning() } func setRectInterest(_ orignRect: CGRect) { let bounds = UIScreen.main.bounds let x: CGFloat = orignRect.origin.x / bounds.size.width let y: CGFloat = orignRect.origin.y / bounds.size.height let width: CGFloat = orignRect.size.width / bounds.size.width let height: CGFloat = orignRect.size.height / bounds.size.height output.rectOfInterest = CGRect(x: y, y: x, width: height, height: width) } class func detectorQRCodeImage(_ image: UIImage, isDrawQRCodeFrame: Bool = true,drawLineWidth:CGFloat = 5) -> (resultStrs: [String]?, resultImage: UIImage) { let imageCI = CIImage(image: image) let dector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]) let features = dector?.features(in: imageCI!) var resultImage = image var resultStrings = [String]() for feature in features! { let qrFeature = feature as! CIQRCodeFeature resultStrings.append(qrFeature.messageString!) if isDrawQRCodeFrame { resultImage = drawFrame(resultImage, feature: qrFeature,drawLineWidth:drawLineWidth) } } return (resultStrings, resultImage) } class func generatorQRCode(_ inputStr: String, centerImage: UIImage?,scaleXY: CGFloat = 20,drawSize:CGSize = CGSize(width: 80, height: 80)) -> UIImage { let filter = CIFilter(name: "CIQRCodeGenerator") filter?.setDefaults() filter?.setValue(inputStr.data(using: String.Encoding.utf8), forKey: "inputMessage") filter?.setValue("M", forKey: "inputCorrectionLevel") var image = filter?.outputImage let transform = CGAffineTransform(scaleX: scaleXY, y: scaleXY) image = image?.applying(transform) var resultImage = UIImage(ciImage: image!) if centerImage != nil { resultImage = mergeImage(resultImage, centerImage: centerImage!,centerImageSize:drawSize) } return resultImage }}extension QRTool { class fileprivate func drawFrame(_ image: UIImage, feature: CIQRCodeFeature,drawLineWidth:CGFloat) -> UIImage { let size = image.size UIGraphicsBeginImageContext(size) image.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) let context = UIGraphicsGetCurrentContext() context?.scaleBy(x: 1, y: -1) context?.translateBy(x: 0, y: -size.height) let bounds = feature.bounds let path = UIBezierPath(rect: bounds) UIColor.red.setStroke() path.lineWidth = drawLineWidth path.stroke() let resultImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return resultImage! } class fileprivate func mergeImage(_ sourceImage: UIImage, centerImage: UIImage,centerImageSize : CGSize = CGSize(width: 80, height: 80)) -> UIImage { let size = sourceImage.size UIGraphicsBeginImageContext(size) sourceImage.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height)) centerImage.draw(in: CGRect(x: (size.width - centerImageSize.width) * 0.5, y: (size.height - centerImageSize.height) * 0.5, width: centerImageSize.width, height: centerImageSize.height)) let resultImage = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return resultImage! }}extension QRTool: AVCaptureMetadataOutputObjectsDelegate { func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) { if isDrawFrame { removeFrameLayer() } var resultStrs = [String]() for obj in metadataObjects { if (obj as AnyObject).isKind(of: AVMetadataMachineReadableCodeObject.self){ let resultObj = previewLayer.transformedMetadataObject(for: obj as! AVMetadataObject) let qrCodeObj = resultObj as! AVMetadataMachineReadableCodeObject if !resultStrs.contains(qrCodeObj.stringValue){ resultStrs.append(qrCodeObj.stringValue) } if isDrawFrame { drawFrame(qrCodeObj) } } } if scanResultBlock != nil { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()) { print("--now--") self.removeFrameLayer() self.scanResultBlock!(resultStrs)//代理转闭包 } } } func drawFrame(_ qrCodeObj: AVMetadataMachineReadableCodeObject) { guard let corners = qrCodeObj.corners else { return } let shapLayer = CAShapeLayer() shapLayer.fillColor = UIColor.clear.cgColor shapLayer.strokeColor = drawStrokeColor.cgColor shapLayer.fillColor = UIColor.clear.cgColor shapLayer.lineWidth = drawLindWidth let path = UIBezierPath() var index = 0 for corner in corners { let point = CGPoint(dictionaryRepresentation:corner as! CFDictionary) if index == 0 { path.move(to: point!) }else { path.addLine(to: point!) } index += 1 } path.close() shapLayer.path = path.cgPath previewLayer.addSublayer(shapLayer) } func removeFrameLayer() { guard let subLayers = previewLayer.sublayers else {return} for subLayer in subLayers { if subLayer.isKind(of: CAShapeLayer.self){ subLayer.removeFromSuperlayer() } } }}
在你的调用处用如下示例代码
//// ViewController.swift// QRToolDemo//// Created by targetcloud on 2016/12/4.// Copyright © 2016年 targetcloud. All rights reserved.//import UIKitclass ViewController: UIViewController { @IBOutlet weak var QRCodeResultStrings: UITextField! @IBOutlet weak var scanline: UIImageView! @IBOutlet weak var scanBackView: UIView! @IBOutlet weak var scanlineBottomConstraint: NSLayoutConstraint! @IBOutlet weak var qrImg: UIImageView! deinit{ print("demo deinit"); } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { QRCodeResultStrings.resignFirstResponder() } override func viewDidLoad() { super.viewDidLoad() scanBackView.backgroundColor = UIColor.clear scanBackView.clipsToBounds = true self.title="--QRTool Demo--"; let leftItem=UIBarButtonItem(barButtonSystemItem:.action,target:self,action:#selector(ViewController.ItemClick)); self.navigationItem.leftBarButtonItem=leftItem; } func ItemClick(){ self.navigationController?.popViewController(animated: true); } //生成二维码图片 @IBAction func generatorQRImage(_ sender: UIButton) { view.endEditing(true) let resultImage = QRTool.generatorQRCode(QRCodeResultStrings.text ?? "", centerImage: UIImage(named: "targetcloud.png")) qrImg.image = resultImage } //add NSPhotoLibraryUsageDescription key in your info.plist //从相册检测到二维码 @IBAction func detectFromImagePickerController(_ sender: UIButton) { if !UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary){ return } let imagePickerVC = UIImagePickerController() imagePickerVC.delegate = self present(imagePickerVC, animated: true, completion: nil) } //add NSCameraUsageDescription key in your info.plist //从相机扫描二维码 @IBAction func startScan(_ sender: UIButton) { startScanAnimation() QRTool.shareInstance.setRectInterest(scanBackView.frame) QRTool.shareInstance.scanQRCode(view) { [weak self] (resultStrs) in//需要加[weak self] guard let str = resultStrs.first else { return } self?.QRCodeResultStrings.text = str QRTool.shareInstance.session.stopRunning(); QRTool.shareInstance.previewLayer.removeFromSuperlayer(); self?.removeScanAnimation() //前往扫描结果 self?.go(str) } } fileprivate func startScanAnimation() { scanlineBottomConstraint.constant = -scanBackView.frame.size.height view.layoutIfNeeded() scanlineBottomConstraint.constant = scanBackView.frame.size.height UIView.animate(withDuration: 1, animations: { UIView.setAnimationRepeatCount(MAXFLOAT) self.view.layoutIfNeeded() }) } fileprivate func removeScanAnimation() { scanline.layer.removeAllAnimations() } fileprivate func go(_ str : String){ var msg:String var title:String if str.characters.count==0 { msg = "没有得到相关信息。。。" title = "OK" }else{ msg = str.description title = "前往" } let alertVC = UIAlertController(title: "结果", message: msg, preferredStyle: UIAlertControllerStyle.alert) let action = UIAlertAction(title: title, style: UIAlertActionStyle.default) { (action: UIAlertAction) in if str.characters.count>0{ UIApplication.shared.open(URL(string: str)!, options: [:], completionHandler: nil) } } alertVC.addAction(action) present(alertVC, animated: true, completion: nil) }}extension ViewController:UINavigationControllerDelegate, UIImagePickerControllerDelegate{ func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { guard let image = info[UIImagePickerControllerOriginalImage] as? UIImage else{ return } let result = QRTool.detectorQRCodeImage(image) QRCodeResultStrings.text = result.resultStrs?.last ?? "" picker.dismiss(animated: true, completion: nil) //前往检测结果 go(QRCodeResultStrings.text!) }}
效果图
0 0
- 二维码系列(五)综合DEMO演练,工具类效能提升
- 二维码系列(四)二维码工具类的封装和使用,非常经典,拿走不谢
- RN综合演练(TabBarIOS、NavigatorIOS)
- 阿里云推出应用配置管理新工具 助力企业效能几何式提升
- 二维码(Logo)工具类
- 得到综合(五)
- 工具类库系列(五)-Timer
- RN综合演练,仿美团电商(谢谢你的STAR)
- java 二维码工具类(二维码生成 解析)
- 综合Demo
- WEBSHELL权限提升技巧(综合版)
- SQL语句优化提升整体效能
- 黑暗中的管理效能提升总结
- 二维码 Demo
- 二维码工具类
- 二维码工具类
- 二维码工具类
- 二维码生成工具类
- C语言编译数组地址分配问题
- MOS管知识
- 小案例-健康栏目的实现分析
- Codeforces Round #379 (Div. 2)E. Anton and Tree(dfs缩点,想法题)
- Origin中做fillarea填充图
- 二维码系列(五)综合DEMO演练,工具类效能提升
- 健康栏目的实现
- 函数式编程之 Lambda 表达式的引出_Java8 实践
- 网页共用头部或共用底部该如何编写代码
- java double转string
- unity 3d GUI.Button介绍
- LeetCode 86 Partition List
- If I were a boy
- php将数据下载到服务器压缩后上传至FTP