QR Scanner in Swift

import AVFoundation
extension ViewController: AVCaptureMetadataOutputObjectsDelegate {}
func createCaptureSession() throws -> AVCaptureSession {captureSession = AVCaptureSession()guard let captureDevice = AVCaptureDevice.default(for: .video) else {print("Device error")throw QRScannerError.videoNotSupported}guard let videoInput = try? AVCaptureDeviceInput(device: captureDevice) else {throw QRScannerError.unableToCrateCaptureDeviceInput}print(videoInput)guard captureSession.canAddInput(videoInput) else {throw QRScannerError.cannotAddSessionCaptureDeviceInput}captureSession.addInput(videoInput)let metadataOutput = AVCaptureMetadataOutput()guard captureSession.canAddOutput(metadataOutput) else {throw QRScannerError.cannotAddSessionCaptureMetadataOutput}captureSession.addOutput(metadataOutput)metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)metadataOutput.metadataObjectTypes = [.qr]captureSessionConfigured = truereturn captureSession}
func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {stopRunning()guard let readableCodeObject = metadataObjects.first  as? AVMetadataMachineReadableCodeObject  else {delegate?.qrScanning(result: .failure(.qrNotAvailable))return}@QRValidator var qrCode: String? = readableCodeObject.stringValueguard let qr = qrCode else {delegate?.qrScanning(result: .failure(.qrNotAvailable))return}AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))delegate?.qrScanning(result: .success(qr))}
private var scanner: QRScanner!
private func startCapturing(session: AVCaptureSession) {//Initialize video preview layer and add as subviewpreviewLayer = AVCaptureVideoPreviewLayer(session: session)previewLayer.frame = self.view.layer.bounds
previewLayer.videoGravity = .resizeAspectFillcameraView.layer.addSublayer(previewLayer)//start video capture_ = scanner.startRunning()
scannerView.layer.borderColor = UIColor.white.cgColorscannerView.layer.borderWidth = 3self.setupConstraints()
view.addSubview(torchLabel)view.addSubview(torchButton)view.bringSubviewToFront(torchButton)view.addSubview(scannerView)view.bringSubviewToFront(scannerView)view.addSubview(bottomView)view.bringSubviewToFront(bottomView)
setupMaskLayer()}
//setup mask layerlet maskLayer = CAShapeLayer()func setupMaskLayer() {self.maskLayer.removeFromSuperlayer()let path = CGMutablePath()path.addRect(cameraView.bounds)path.addRect(scannerView.frame)maskLayer.path = pathmaskLayer.fillColor = UIColor(red: 61.0 / 255.0, green: 56.0 / 255.0, blue: 56.0 / 255.0, alpha: 0.5).cgColormaskLayer.fillRule = .evenOddcameraView.layer.addSublayer(maskLayer)}
// If you are doing this in view controller:
open override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
setupMaskLayer()
}

// If you are doing this in UIView using auto-layout
override func layoutSubviews() {
super.layoutSubviews()
setupMaskLayer()
}

// If you are doing this in UIView using manual setting of frame
override var frame: CGRect {
didSet {
setupMaskLayer()
}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store