Swift4 相机二维码扫描
2017-11-07 本文已影响151人
东城夕阳
Swift4相机扫描二维码,复制粘贴拿走不谢😄😄😄
![](https://img.haomeiwen.com/i4284907/4fe524eab62a8bda.gif)
//
// QRCodeScanViewController.swift
// TaoLiveShow
//
// Created by 黄明可 on 2017/5/11.
// Copyright © 2017年 黄明可. All rights reserved.
//
import UIKit
import AVFoundation
/// 屏幕宽度
let kScreenWidth = UIScreen.main.bounds.size.width
/// 屏幕高度
let kScreenHeight = UIScreen.main.bounds.size.height
/// 导航条高度
let kNavigationHeight = UIApplication.shared.statusBarFrame.height
/// 中间扫描框的高度
private let kBoxW : CGFloat = kScreenWidth * 0.5
/// 中间扫描框的中间点的Y
private let kBoxCentY : CGFloat = kScreenHeight * 0.4
//中间扫描框的四个顶点
private let leftTopPoint = CGPoint.init(x: (kScreenWidth - kBoxW)/2, y: (kBoxCentY - (kBoxW/2)))
private let rightTopPoint = CGPoint.init(x: (kScreenWidth + kBoxW)/2, y: (kBoxCentY - (kBoxW/2)))
private let rightBottomPoint = CGPoint.init(x: (kScreenWidth + kBoxW)/2, y: (kBoxCentY + (kBoxW/2)))
private let leftBottomPoint = CGPoint.init(x: (kScreenWidth - kBoxW)/2, y: (kBoxCentY + (kBoxW/2)))
class QRCodeScanViewController: UIViewController {
/// 扫描会话
var session = AVCaptureSession()
/// 预览图层
lazy var preview : AVCaptureVideoPreviewLayer = {
let preview = AVCaptureVideoPreviewLayer.init(session: self.session)
preview.videoGravity = AVLayerVideoGravity.resizeAspectFill
preview.frame = CGRect.init(x: 0, y: kNavigationHeight, width: kScreenWidth, height:kScreenHeight - kNavigationHeight)
preview.backgroundColor = UIColor.black.cgColor
let bpath : UIBezierPath = UIBezierPath.init(rect: self.view.bounds)
let shaplayer = CAShapeLayer()
shaplayer.frame = preview.bounds
let path = self.createBezierPath(points: [leftTopPoint,rightTopPoint,rightBottomPoint,leftBottomPoint])
bpath.append(path)
shaplayer.path = bpath.cgPath
shaplayer.fillColor = UIColor.black.withAlphaComponent(0.4).cgColor
shaplayer.fillRule = kCAFillRuleEvenOdd
let edgeWidth : CGFloat = 30
let edgeSize = CGSize.init(width: edgeWidth, height: edgeWidth)
let edgeLineWidth : CGFloat = 2
let leftTopLayer = CAShapeLayer()
leftTopLayer.frame = CGRect.init(origin: leftTopPoint, size: edgeSize)
let leftTopPath = self.createBezierPath(points: [CGPoint.init(x: 0, y: 0),CGPoint.init(x: edgeWidth, y: 0),CGPoint.init(x: edgeWidth, y: edgeLineWidth),CGPoint.init(x: edgeLineWidth, y: edgeLineWidth),CGPoint.init(x: edgeLineWidth, y: edgeWidth),CGPoint.init(x: 0, y: edgeWidth)])
leftTopLayer.path = leftTopPath.cgPath
leftTopLayer.fillColor = UIColor.green.cgColor
let rightTopLayer = CAShapeLayer()
rightTopLayer.frame = CGRect.init(origin: CGPoint.init(x: rightTopPoint.x - edgeWidth, y: rightTopPoint.y), size: edgeSize)
let rightTopPath = self.createBezierPath(points: [CGPoint.init(x: edgeWidth, y: 0),CGPoint.init(x: 0, y: 0),CGPoint.init(x: 0, y: edgeLineWidth),CGPoint.init(x: edgeWidth - edgeLineWidth, y: edgeLineWidth),CGPoint.init(x: edgeWidth - edgeLineWidth, y: edgeWidth),CGPoint.init(x: edgeWidth, y: edgeWidth)])
rightTopLayer.path = rightTopPath.cgPath
rightTopLayer.fillColor = UIColor.green.cgColor
let rightBottomLayer = CAShapeLayer()
rightBottomLayer.frame = CGRect.init(origin: CGPoint.init(x: rightBottomPoint.x - edgeWidth, y: rightBottomPoint.y - edgeWidth), size: edgeSize)
let rightBottomPath = self.createBezierPath(points: [CGPoint.init(x: edgeWidth, y: edgeWidth),CGPoint.init(x: edgeWidth, y: 0),CGPoint.init(x: edgeWidth - edgeLineWidth, y: 0),CGPoint.init(x: edgeWidth - edgeLineWidth, y: edgeWidth - edgeLineWidth),CGPoint.init(x: 0, y: edgeWidth - edgeLineWidth),CGPoint.init(x: 0, y: edgeWidth)])
rightBottomLayer.path = rightBottomPath.cgPath
rightBottomLayer.fillColor = UIColor.green.cgColor
let leftBottomLayer = CAShapeLayer()
leftBottomLayer.frame = CGRect.init(origin: CGPoint.init(x: leftBottomPoint.x, y: leftBottomPoint.y - edgeWidth), size: edgeSize)
let leftBottomPath = self.createBezierPath(points: [CGPoint.init(x: 0, y: edgeWidth),CGPoint.init(x: edgeWidth, y: edgeWidth),CGPoint.init(x: edgeWidth, y: edgeWidth - edgeLineWidth),CGPoint.init(x: edgeLineWidth, y: edgeWidth - edgeLineWidth),CGPoint.init(x: edgeLineWidth, y: 0),CGPoint.init(x: 0, y: 0)])
leftBottomLayer.path = leftBottomPath.cgPath
leftBottomLayer.fillColor = UIColor.green.cgColor
preview.addSublayer(shaplayer)
preview.addSublayer(leftTopLayer)
preview.addSublayer(rightTopLayer)
preview.addSublayer(rightBottomLayer)
preview.addSublayer(leftBottomLayer)
return preview
}()
lazy var animalLine : UIImageView = {
let line = UIImageView.init(image: UIImage.init(named: "qrcode_scan_animal"))
self.view.addSubview(line)
return line
}()
var isAnimal : Bool?
lazy var prompt : UILabel = {
let prompt = UILabel.init(frame: CGRect.init(x: leftBottomPoint.x, y: leftBottomPoint.y + kNavigationHeight + 10, width: kBoxW, height: 60))
prompt.text = "将二维码放入扫描框即可自动扫描"
prompt.textAlignment = .center
prompt.font = UIFont.systemFont(ofSize: 15)
prompt.textColor = UIColor.white
prompt.numberOfLines = 0
prompt.sizeToFit()
return prompt
}()
var timer : Timer?
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
stopRunning()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
startRunning()
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "扫描二维码"
/// 获取设备
let devices = AVCaptureDevice.devices(for: .video)
let d = devices.filter({ return $0.position == .back }).first
/// 视频输入
let videoInput = try? AVCaptureDeviceInput(device: d!)
let queue = DispatchQueue.global(qos: .default)
let videoOutput = AVCaptureMetadataOutput()
videoOutput.setMetadataObjectsDelegate(self, queue: queue)
if session.canAddInput(videoInput!) {
session.addInput(videoInput!)
}
if session.canAddOutput(videoOutput) {
session.addOutput(videoOutput)
}
///扫描类型
videoOutput.metadataObjectTypes = [
.qr,
.code39,
.code128,
.code39Mod43,
.ean13,
.ean8,
.code93]
///可识别区域 注意看这个rectOfInterest 不是一左上角为原点,以右上角为原点 并且rect的值是个比例在【0,1】之间
videoOutput.rectOfInterest = CGRect.init(x: (kBoxCentY - (kBoxW/2) + kNavigationHeight/2)/kScreenHeight, y: 1 - (kScreenWidth + kBoxW)/2/kScreenWidth, width: kBoxW/kScreenHeight, height: kBoxW/kScreenWidth)
view.layer.addSublayer(preview)
self.view.addSubview(prompt)
}
func createBezierPath( points : [CGPoint]) -> UIBezierPath {
var points = points
let path = UIBezierPath()
path.move(to: points.first!)
points.remove(at: 0)
for point in points {
path.addLine(to: point)
}
path.close()
return path
}
/// 开始扫描
func startRunning() {
session.startRunning()
setupTimer()
}
@objc func animalStart() {
view.bringSubview(toFront: self.animalLine)
animalLine.frame = CGRect.init(x: leftTopPoint.x, y: leftTopPoint.y + kNavigationHeight , width: kBoxW, height: 1)
UIView.animate(withDuration: 3, animations: {
let frame = self.animalLine.frame
let newY : CGFloat = leftTopPoint.y + kNavigationHeight + kBoxW - frame.size.height
let newFrame = CGRect.init(x: frame.origin.x, y: newY, width: frame.size.width, height: frame.size.height)
self.animalLine.frame = newFrame
}) { (finish) in
}
}
/// 结束扫描
func stopRunning() {
session.stopRunning()
timer?.invalidate()
}
func setupTimer() {
self.animalStart()
self.timer = Timer.init(timeInterval: 3, target: self, selector: #selector(animalStart), userInfo: nil, repeats: true)
RunLoop.main.add(self.timer!, forMode: RunLoopMode.commonModes)
}
deinit {
print("dealloc")
}
}
extension QRCodeScanViewController : AVCaptureMetadataOutputObjectsDelegate
{
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
//扫描结果
print(output)
if metadataObjects.count > 0 {
let obj : AVMetadataMachineReadableCodeObject = metadataObjects.first as! AVMetadataMachineReadableCodeObject
let str : String = obj.stringValue!
print(str)
stopRunning()
}
}
}