import UIKit
let screenWidth: CGFloat = UIScreen.main.bounds.size.width
let screenHeight: CGFloat = UIScreen.main.bounds.size.height
let screenRadio: CGFloat = screenWidth / 375.0
let scanQRCodeWidth: CGFloat = 250 * screenRadio
let scanQRCodeTop: CGFloat = 124 * screenRadio
class SCanMaskView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .clear
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
guard let con = UIGraphicsGetCurrentContext() else {
return
}
con.setFillColor(UIColor.black.withAlphaComponent(0.5).cgColor)
con.fill(rect)
con.clear(CGRect(x: (screenWidth - scanQRCodeWidth) / 2.0, y: scanQRCodeTop, width: scanQRCodeWidth, height: scanQRCodeWidth))
//設(shè)置線條樣式
con.setLineCap(.square)
//設(shè)置線條粗細(xì)寬度
con.setLineWidth(4.0)
//設(shè)置顏色
con.setStrokeColor(UIColor(red: 229 / 255.0, green: 0, blue: 50 / 255.0, alpha: 1.0).cgColor)
//開始一個起始路徑
con.beginPath()
//起始點(diǎn)設(shè)置為(100,100):注意這是上下文對應(yīng)區(qū)域中的相對坐標(biāo)盒使,
con.move(to: CGPoint(x: (screenWidth - scanQRCodeWidth) / 2 + 10, y: scanQRCodeTop))
//設(shè)置下一個坐標(biāo)點(diǎn)
con.addLine(to: CGPoint(x: (screenWidth - scanQRCodeWidth ) / 2, y: scanQRCodeTop))
//設(shè)置下一個坐標(biāo)點(diǎn)
con.addLine(to: CGPoint(x: (screenWidth - scanQRCodeWidth ) / 2, y: scanQRCodeTop + 10))
//連接上面定義的坐標(biāo)點(diǎn)
con.strokePath()
//開始一個起始路徑
con.beginPath()
//起始點(diǎn)設(shè)置為(100,100):注意這是上下文對應(yīng)區(qū)域中的相對坐標(biāo),
con.move(to: CGPoint(x: (screenWidth - scanQRCodeWidth) / 2 + scanQRCodeWidth - 10, y: scanQRCodeTop))
//設(shè)置下一個坐標(biāo)點(diǎn)
con.addLine(to: CGPoint(x: (screenWidth - scanQRCodeWidth ) / 2 + scanQRCodeWidth , y: scanQRCodeTop))
//設(shè)置下一個坐標(biāo)點(diǎn)
con.addLine(to: CGPoint(x: (screenWidth - scanQRCodeWidth ) / 2 + scanQRCodeWidth, y: scanQRCodeTop + 10))
//連接上面定義的坐標(biāo)點(diǎn)
con.strokePath()
//開始一個起始路徑
con.beginPath()
//起始點(diǎn)設(shè)置為(100,100):注意這是上下文對應(yīng)區(qū)域中的相對坐標(biāo)径簿,
con.move(to: CGPoint(x: (screenWidth - scanQRCodeWidth) / 2 + scanQRCodeWidth - 10, y: scanQRCodeTop + scanQRCodeWidth))
//設(shè)置下一個坐標(biāo)點(diǎn)
con.addLine(to: CGPoint(x: (screenWidth - scanQRCodeWidth ) / 2 + scanQRCodeWidth, y: scanQRCodeTop + scanQRCodeWidth))
//設(shè)置下一個坐標(biāo)點(diǎn)
con.addLine(to: CGPoint(x: (screenWidth - scanQRCodeWidth ) / 2 + scanQRCodeWidth, y: scanQRCodeTop + scanQRCodeWidth - 10))
//連接上面定義的坐標(biāo)點(diǎn)
con.strokePath()
//開始一個起始路徑
con.beginPath()
//起始點(diǎn)設(shè)置為(100,100):注意這是上下文對應(yīng)區(qū)域中的相對坐標(biāo),
con.move(to: CGPoint(x: (screenWidth - scanQRCodeWidth) / 2 + 10, y: scanQRCodeTop + scanQRCodeWidth))
//設(shè)置下一個坐標(biāo)點(diǎn)
con.addLine(to: CGPoint(x: (screenWidth - scanQRCodeWidth ) / 2, y: scanQRCodeTop + scanQRCodeWidth))
//設(shè)置下一個坐標(biāo)點(diǎn)
con.addLine(to: CGPoint(x: (screenWidth - scanQRCodeWidth ) / 2, y: scanQRCodeTop + scanQRCodeWidth - 10))
//連接上面定義的坐標(biāo)點(diǎn)
con.strokePath()
}
}
import UIKit
import AVFoundation
class ScanQRCodeViewController: UIViewController {
var session: AVCaptureSession!
var scanLine: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
buildUI()
}
func buildUI() {
scanQRCode()
let maskView = SCanMaskView(frame: view.bounds)
view.addSubview(maskView)
}
func scanQRCode() {
guard let device = AVCaptureDevice.default(for: .video) else { return }
do {
//創(chuàng)建輸入流
let input = try AVCaptureDeviceInput(device: device)
//創(chuàng)建輸出流
let output = AVCaptureMetadataOutput()
//設(shè)置會話
session = AVCaptureSession()
if session.canSetSessionPreset(.high) {
session.sessionPreset = .high
}
//連接輸入輸出流
if session.canAddInput(input) {
session.addInput(input)
}
if session.canAddOutput(output) {
session.addOutput(output)
}
//設(shè)置掃描碼的類型
output.metadataObjectTypes = [.qr, .ean13, .ean8, .code128]
//設(shè)置掃描區(qū)域
output.rectOfInterest = CGRect(x: scanQRCodeTop / screenHeight, y: (( screenWidth - scanQRCodeWidth ) / 2 ) / screenWidth, width: scanQRCodeWidth / screenHeight, height: scanQRCodeWidth / screenWidth)
//捕捉圖層
let previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer.videoGravity = .resizeAspectFill
previewLayer.frame = view.layer.bounds
view.layer.insertSublayer(previewLayer, at: 0)
session.startRunning()
}catch {
}
}
}
extension ScanQRCodeViewController: AVCaptureMetadataOutputObjectsDelegate {
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
session.stopRunning()
guard let readableObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject else {
return
}
if let str = readableObject.stringValue {
print(str)
}
}
}