Implement scanning QRCode ViewController via AVCaptureSession, AVCaptureMetadataOutput and AVCaptureVideoPreviewLayer
Prerequisite
Initialization
Carry out all the initializations in viewDidLoad
Initialize AVCaptureSession
1
| captureSession = AVCaptureSession()
|
1 2 3 4 5 6 7 8 9 10 11 12
| guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else{ return } guard let videoInput = try? AVCaptureDeviceInput(device: videoCaptureDevice) else{ return }
if (captureSession.canAddInput(videoInput)) { captureSession.addInput(videoInput) } else { return }
|
Use AVCaptureMetadataOutput for capturing QRCode or others
Metadata object type:
.qr -> QRCode
.code128 -> Bar code
1 2 3 4 5 6 7 8 9
| let metadataOutput = AVCaptureMetadataOutput() if (captureSession.canAddOutput(metadataOutput)) { captureSession.addOutput(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main) metadataOutput.metadataObjectTypes = [.qr, .code128] } else { return }
|
Add preview layer to the ViewController
1 2 3 4
| previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) previewLayer.frame = view.layer.bounds previewLayer.videoGravity = .resizeAspectFill view.layer.addSublayer(previewLayer)
|
Start capture session
1 2 3
| DispatchQueue.global().async { self.captureSession.startRunning() }
|
Start & Stop capture session
Start the capture session when view appears and stop the capture session when view disappears
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) if (captureSession?.isRunning == false) { DispatchQueue.global().async { self.captureSession.startRunning() } } }
override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated)
if (captureSession?.isRunning == true) { captureSession.stopRunning() } }
|
Implement the delegate
Implement the AVCaptureMetadataOutputObjectsDelegate to get the scan result
1 2 3 4 5 6 7 8 9 10 11 12 13
| extension ScannerViewController: AVCaptureMetadataOutputObjectsDelegate{ func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) { captureSession.stopRunning()
if let metadataObject = metadataObjects.first { guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return } guard let value = readableObject.stringValue else { return } AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate)) } } }
|