1、搭界面(把-54这根约束拖为代码中的属性@IBOutletweakvar scanlineBottomConstraint:NSLayoutConstraint!)
同时在info.plist加入NSCameraUsageDescription
2、代码
// // ViewController.swift // ScanQR // // Created by targetcloud on 2016/12/3. // Copyright © 2016年 targetcloud. All rights reserved. // import UIKit import AVFoundation class ViewController: UIViewController { @IBOutlet weak var scanline: UIImageView! @IBOutlet weak var scanBackView: UIView! @IBOutlet weak var scanlineBottomConstraint: NSLayoutConstraint! var session: AVCaptureSession? weak var previewShapelayer: AVCaptureVideoPreviewLayer? override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) startScanAnimation() startScan() } //add NSCameraUsageDescription key in info.plist! override func viewDidLoad() { super.viewDidLoad() scanBackView.backgroundColor = UIColor.clear scanBackView.clipsToBounds = true } func startScan() { let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo) var input: AVCaptureDeviceInput? do { input = try AVCaptureDeviceInput(device: device) }catch { return } let output = AVCaptureMetadataOutput() output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main) session = AVCaptureSession() if session!.canAddInput(input) && session!.canAddOutput(output) { session!.addInput(input) session!.addOutput(output) }else { return } output.metadataObjectTypes = [AVMetadataObjectTypeQRCode] let bounds = UIScreen.main.bounds let x: CGFloat = scanBackView.frame.origin.x / bounds.size.width let y: CGFloat = scanBackView.frame.origin.y / bounds.size.height let width: CGFloat = scanBackView.frame.size.width / bounds.size.width let height: CGFloat = scanBackView.frame.size.height / bounds.size.height output.rectOfInterest = CGRect(x: y, y: x, width: height, height: width) let layer = AVCaptureVideoPreviewLayer(session: session) layer?.frame = view.layer.bounds view.layer.insertSublayer(layer!, at: 0) self.previewShapelayer = layer session!.startRunning() } } extension ViewController: AVCaptureMetadataOutputObjectsDelegate { func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) { removeFrameLayer() print(metadataObjects) for obj in metadataObjects { if (obj as AnyObject).isKind(of: AVMetadataMachineReadableCodeObject.self){ let resultObj = self.previewShapelayer?.transformedMetadataObject(for: obj as! AVMetadataObject) let qrCodeObj = resultObj as! AVMetadataMachineReadableCodeObject print(qrCodeObj.stringValue,qrCodeObj.corners) drawFrame(qrCodeObj) } } } func drawFrame(_ qrCodeObj: AVMetadataMachineReadableCodeObject) { let corners = qrCodeObj.corners let shapeLayer = CAShapeLayer() shapeLayer.fillColor = UIColor.clear.cgColor shapeLayer.strokeColor = UIColor.red.cgColor shapeLayer.lineWidth = 5 let path = UIBezierPath() var index = 0 for corner in corners! { let pointDic = corner as! CFDictionary let point = CGPoint(dictionaryRepresentation:pointDic)! if index == 0 { path.move(to: point) }else { path.addLine(to: point) } index += 1 } path.close() shapeLayer.path = path.cgPath self.previewShapelayer?.addSublayer(shapeLayer) } func removeFrameLayer() { guard let subLayers = self.previewShapelayer?.sublayers else {return} for subLayer in subLayers { if subLayer.isKind(of: CAShapeLayer.self){ subLayer.removeFromSuperlayer() } } } } extension ViewController { 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() }) } func removeScanAnimation() { scanline.layer.removeAllAnimations() } } /* print(metadataObjects) [<AVMetadataMachineReadableCodeObject: 0x16d81590, type="org.iso.QRCode", bounds={ 0.4,0.4 0.1x0.2 }>corners { 0.4,0.6 0.5,0.6 0.5,0.4 0.4,0.4 }, time 44181676151916, stringValue "http://weixin.qq.com/r/iEyyqvnEfaQCrb3J9xma"] print(qrCodeObj.stringValue,qrCodeObj.corners) https://github.com/targetcloud/DYZB [{ X = "86.91517"; Y = "186.571"; }, { X = "88.79387"; Y = "311.6888"; }, { X = "212.8607"; Y = "313.2776"; }, { X = "215.6975"; Y = "187.0925"; }] */3、运行效果(在限定的框内扫描到会画出红框)
使用工具类扫描二维码见二维码系列(4)
