QR Code

An QR (Quick Response) code is two dimensional barcode. It can carry information in both vertical and horizontal direction. QR code can be used to display product descriptions, provide URLs/address, give contact cards, initiate payments, deeplink any iOS application. It is used to market and advertise the brands.

In iOS, QR code can be scanned using default Camera app. Also, certain apps use their own QR code scanner to maintain their in-app experience, accessibility and invoke specific functionality. A custom interface to scan QR can be build using AVFoundation framework.

Configuring Capture Session

AVCaptureSession manages the audio & video sessions in iOS. AVCaptureDevice is the physical capturing device present in your phone and it gives one or more AVCaptureOutputs. We will use default camera as input and the output will be instance of AVCaptureMetadataOutput that will provide us metadata of the video session. The output type of the metadata can be set by setting metadataObjectTypes to .qr

func captureSession() {
    guard let videoDevice = deviceType.default(for: .video),
        let captureInput = try? AVCaptureDeviceInput(device: videoDevice),
        session.canAddInput(captureInput) else {
            //If the device is not present/cannot be added to the capturing session.
            return
    }

    let metaOutput = AVCaptureMetadataOutput()
    guard session.canAddOutput(metaOutput) else {
        //If the output cannot be added to the capturing session.
        return
    }

    session.addInput(captureInput)
    session.addOutput(metaOutput)

    guard metaOutput.availableMetadataObjectTypes.contains(.qr) else {
        //QR metadata output not present in this device
        return
    }

    metadataOutput.metadataObjectTypes = [.qr]
    metadataOutput.setMetadataObjectsDelegate(self, queue: queue)
}

Loading Camera

We need to provide permission to access camera. To request for permission we must add NSCameraUsageDescription key to info.plist with description stating why do we need access the camera. To load a Camera view, we must create custom view with AVCaptureVideoPreviewLayer as its sublayer. The session can be initiated by calling startRunning

func requestPermission() {
    switch AVCaptureDevice.authorizationStatus(for: AVMediaType.video) {
    case .authorized:
    // If authorized to access the camera.
    case .notDetermined:
        // We have never requested access to the camera before.
        AVCaptureDevice.requestAccess(for: .video) { authorized in
                guard authorized else {
                    // Denied the camera access request.
                    return
                }
                // Authorized to access the camera.
            }
        }
    case .denied, .restricted:
        // Denied the camera access request or if camera usage is restriced.
        return
    }
}

Scanning QR Code

We will look how to extract URL from QR code. We have set up camera video session, configured our video preview layer and permission to access camera is granted by user. AVCaptureMetaDataOutputObjectsDelegate provides a delegate method captureOutput:didOutputMetadataObjects:fromConnection: that is called when QR code is scanned.

func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        guard let object = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
            let stringValue = object.stringValue,
            let url = URL(string: stringValue) else do {
                return
        }
        //If the URL is valid, perform required action
    }

Thus, we have implemented custom QR code scanner, which will enable user to perform multiple actions by identifying QR code.

blog

copyright©2021Saravana all rights reserved