To capture a user’s driver license data, you’ll use DriverLicenseScannerViewController to create the DriverLicense object containing the data.

Driver licenses issued in USA and Canada have the PDF417 code per the AAMVA Standard. The IDScanner class defines a composite protocol which is used by the DriverLicenseScannerViewController to find the barcode, if applicable, and extract metadata from the barcode.

By default, AVCaptureMetadataOutput from the AVFoundation framework is used to detect 1D and 2D barcodes. If you want to use a different barcode detector, you can wrap it in IDScanner and pass it to the Builder.

Ensure that you’ve added the UI library to your Podfile or View Controller. See Add the dependencies needed for your application for more information.

Initializing DriverLicenseScannerViewController

Initialize DriverLicenseScannerViewController.Builder with either a DriverLicenseScannerListener object or closure blocks to receive completion events with the result.

Here’s an example initializing DriverLicenseScannerViewController:

class YourViewController: UIViewController, DriverLicenseScannerListener {

    override func viewDidAppear() {
        super.viewDidAppear()

        try DriverLicenseScannerViewController.Builder { (isComplete, license) in
            guard isComplete,
                  let driverLicense = license else {
                // Canceled
                return
            }
            
            // Handle DriverLicense here
            
        }.setCheckHasFace(checkHasFace: false) // Defaults to true
        .setSteps(scannerSteps: IDScannerStep.capture_front, IDScannerStep.capture_back)
        // -- OR --
        .setCountry(country: "USA")
        .create().show(parentViewController: self)
    }

}

Because the driver license usually contains a photo ID, you can use setCheckHasFace to indicate whether you want the scanner to confirm that there is at least one face present on the front side of the license. setCheckHasFace is set to true by default.

You can either set the country or pass the scanner steps (scannerSteps) to the Builder. If you set only the country, the scanner will determine the steps based on that. If you set the scanner steps and the country, the scanner steps will always override the country parameter.

The scannerSteps values can be: .capture_front, .capture_back, and .scan_id.

If you start the view controller without passing any scanner steps or country, the UI library will display a country selector to the user, and determine IDScannerSteps based on the selection. You can initialize DriverLicenseScannerViewController using this default behavior. For example:

DriverLicenseScannerViewController.Builder { (isComplete, license) in
            guard isComplete,
                  let driverLicense = license else {
                // Canceled
                return
            }
            
            // Handle DriverLicense here
            
        }.create().show(parentViewController: self)

To get the formatted ‘DriverLicense’ values, use the method ValueFormatter.getFormattedDriverLicense. For example:

ValueFormatter.getFormattedDriverLicense(from: driverLicenseWithRawData)

The default face detector implements SCFaceDetector, and is a wrapper around the iOS class CIDetector for face, from the iOS Core Image Framework. To use a custom face detector, you can use coding similar to this:

try? DriverLicenseScannerViewController.Builder(listener: self)
    .setFaceDetector(faceDetector: YOUR_CUSTOM_FACE_DETECTOR)
    .create()
    .show(parentViewController: self)

You can also pass your custom barcode scanner wrapped as IDScanner to the Builder. To use a custom bar code scanner, you can use coding similar to this:

try? DriverLicenseScannerViewController.Builder(listener: self)
    .setIdScanner(idScanner: YOUR_CUSTOM_ID_SCANNER)
    .create()
    .show(parentViewController: self)

Getting the resulting DriverLicense object

Use the onDriverLicenseCaptured method to get the DriverLicense object returned by the scanner. For example:

func onDriverLicenseCaptured(license: DriverLicense)

You can also use the boolean hasData to determine whether any metadata is recorded. For example:

func onDriverLicenseCaptured(license: DriverLicense) {
    if let frontImage = license.frontImage,
       let backImage = license.backImage
        // Handle ID images here
    }

    if (license.hasData) {
       // Handle ID Data here
    }

}

To get the formatted ‘DriverLicense’ values, use the method ValueFormatter.getFormattedDriverLicense method. For example:

ValueFormatter.getFormattedDriverLicense(from: driverLicenseWithRawData)