123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- //
- // QRScannerView.swift
- // Gaspol
- //
- // Created by Qindi on 19/05/22.
- //
- import Foundation
- import UIKit
- import AVFoundation
- /// Delegate callback for the QRScannerView.
- protocol QRScannerViewDelegate: AnyObject {
- func qrScanningDidFail()
- func qrScanningSucceededWithCode(_ str: String?)
- func qrScanningDidStop()
- }
- class QRScannerView: UIView {
-
- weak var delegate: QRScannerViewDelegate?
-
- /// capture settion which allows us to start and stop scanning.
- var captureSession: AVCaptureSession?
-
- // Init methods..
- required init?(coder aDecoder: NSCoder) {
- super.init(coder: aDecoder)
- doInitialSetup()
- }
- override init(frame: CGRect) {
- super.init(frame: frame)
- doInitialSetup()
- }
-
- //MARK: overriding the layerClass to return `AVCaptureVideoPreviewLayer`.
- override class var layerClass: AnyClass {
- return AVCaptureVideoPreviewLayer.self
- }
- override var layer: AVCaptureVideoPreviewLayer {
- return super.layer as! AVCaptureVideoPreviewLayer
- }
- }
- extension QRScannerView {
-
- var isRunning: Bool {
- return captureSession?.isRunning ?? false
- }
-
- func startScanning() {
- captureSession?.startRunning()
- }
-
- func stopScanning() {
- captureSession?.stopRunning()
- delegate?.qrScanningDidStop()
- }
-
- /// Does the initial setup for captureSession
- private func doInitialSetup() {
- clipsToBounds = true
- captureSession = AVCaptureSession()
-
- guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else { return }
- let videoInput: AVCaptureDeviceInput
- do {
- videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
- } catch let error {
- //print(error)
- return
- }
-
- if (captureSession?.canAddInput(videoInput) ?? false) {
- captureSession?.addInput(videoInput)
- } else {
- scanningDidFail()
- return
- }
-
- let metadataOutput = AVCaptureMetadataOutput()
-
- if (captureSession?.canAddOutput(metadataOutput) ?? false) {
- captureSession?.addOutput(metadataOutput)
-
- metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
- metadataOutput.metadataObjectTypes = [.qr, .ean8, .ean13, .pdf417]
- } else {
- scanningDidFail()
- return
- }
-
- self.layer.session = captureSession
- self.layer.videoGravity = .resizeAspectFill
-
- captureSession?.startRunning()
- }
- func scanningDidFail() {
- delegate?.qrScanningDidFail()
- captureSession = nil
- }
-
- func found(code: String) {
- delegate?.qrScanningSucceededWithCode(code)
- }
-
- }
- extension QRScannerView: AVCaptureMetadataOutputObjectsDelegate {
- func metadataOutput(_ output: AVCaptureMetadataOutput,
- didOutput metadataObjects: [AVMetadataObject],
- from connection: AVCaptureConnection) {
- stopScanning()
-
- if let metadataObject = metadataObjects.first {
- guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
- guard let stringValue = readableObject.stringValue else { return }
- AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
- found(code: stringValue)
- }
- }
-
- }
|