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)