Class MRZScannerViewController
MRZScannerViewController is a UIViewController subclass that implements MRZ scanning features. It supplies its own full-screen camera UI, so you present it, hand it an MRZScannerConfig, and receive an MRZScanResult through onScannedResult.
Definition
Assembly: DynamsoftMRZScannerBundle.xcframework
- Objective-C
- Swift
@interface DSMRZScannerViewController: UIViewControllerclass MRZScannerViewController: UIViewController
Properties
| Property | Type | Description |
|---|---|---|
config |
DSMRZScannerConfig * | Sets or returns the MRZ scanner configurations. |
onScannedResult |
void (^)(DSMRZScanResult *) | A property that holds a Block. The block is a callback that takes a single parameter of type DSMRZScanResult and returns no value. |
config
Sets or returns the MRZ scanner configurations of type DSMRZScannerConfig.
- Objective-C
- Swift
@property (nonatomic, strong, readwrite) DSMRZScannerConfig * configvar config: MRZScannerConfig = .init()
onScannedResult
A property that holds a Block. The block is a callback that takes a single parameter of type DSMRZScanResult and returns no value.
- Objective-C
- Swift
@property (nonatomic, copy, readwrite) void (^)(DSMRZScanResult *) onScannedResultvar onScannedResult: ((MRZScanResult) -> Void)?
Remarks
Two things about this callback are easy to get wrong:
- It is not called on the main thread. Dispatch to the main queue before touching any UI or SwiftUI state.
- The scanner does not dismiss itself. Whoever presented
MRZScannerViewControlleris responsible for dismissing or popping it when the result arrives.
The images on the result are ARC-managed ImageData objects, so they stay valid for as long as you hold the result — there is no window in which they expire and nothing to convert early. Call toUIImage() when you want a UIImage to hand to a view, or to keep independently of the result.
The callback is invoked exactly once per presentation, for all three values of resultStatus — success, cancellation, and failure all arrive here rather than through separate paths.
How to Use
- Objective-C
- Swift
#import "ViewController.h" #import <DynamsoftMRZScannerBundle/DynamsoftMRZScannerBundle.h> #import <DynamsoftMRZScannerBundle/DynamsoftMRZScannerBundle-Swift.h> @implementation ViewController // Configure a button that presents MRZScannerViewController when tapped. - (void)buttonTapped { DSMRZScannerConfig *config = [[DSMRZScannerConfig alloc] init]; // Required: set a valid license key. config.license = @"DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9"; // Set the document type to scan (default: DSDocumentTypeAll). config.documentType = DSDocumentTypeAll; // Configure which images to include in the result. config.returnDocumentImage = YES; // Cropped document image (default: YES). config.returnPortraitImage = YES; // Portrait image (default: YES). config.returnOriginalImage = NO; // Original full-frame image (default: NO). // Configure UI element visibility. config.isCloseButtonVisible = YES; config.isTorchButtonVisible = YES; config.isCameraToggleButtonVisible = YES; config.isBeepButtonVisible = YES; config.isVibrateButtonVisible = YES; config.isFormatSelectorVisible = YES; config.isGuideFrameVisible = YES; // Configure feedback on a successful scan. config.isBeepEnabled = YES; config.isVibrateEnabled = NO; DSMRZScannerViewController *vc = [[DSMRZScannerViewController alloc] init]; vc.config = config; __weak typeof(self) weakSelf = self; vc.onScannedResult = ^(DSMRZScanResult *result) { // Convert to UIImage here, or later from the result — either works. NSError *error = nil; UIImage *portrait = [[result getPortraitImage] toUIImage:&error]; UIImage *mrzSide = [[result getDocumentImage:DSDocumentSideMrz] toUIImage:&error]; UIImage *oppositeSide = [[result getDocumentImage:DSDocumentSideOpposite] toUIImage:&error]; // The callback runs off the main thread and the scanner does not close // itself, so hop to the main queue and dismiss it here. dispatch_async(dispatch_get_main_queue(), ^{ [weakSelf dismissViewControllerAnimated:YES completion:nil]; switch (result.resultStatus) { case DSResultStatusFinished: { // Scan completed successfully. data is nil for the other statuses. DSMRZData *data = result.data; NSString *mrzText = data.mrzText; NSString *firstName = data.firstName; // Check a single field against its MRZ check digit. DSValidationStatus status = [data getFieldValidationStatus:@"documentNumber"]; break; } case DSResultStatusCanceled: // The user closed the scanner before completing a scan. break; case DSResultStatusException: { // An error occurred during initialization or scanning. NSInteger errorCode = result.errorCode; NSString *errorMessage = result.errorString; break; } } }); }; // The scanner draws its own close button, so present it full screen. vc.modalPresentationStyle = UIModalPresentationFullScreen; [self presentViewController:vc animated:YES completion:nil]; } @endimport UIKit import DynamsoftMRZScannerBundle import DynamsoftCaptureVisionBundle class ViewController: UIViewController { // Configure a button that presents MRZScannerViewController when tapped. @objc func buttonTapped() { let config = MRZScannerConfig() // Required: set a valid license key. config.license = "DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9" // Set the document type to scan (default: .all). config.documentType = .all // Configure which images to include in the result. config.returnDocumentImage = true // Cropped document image (default: true). config.returnPortraitImage = true // Portrait image (default: true). config.returnOriginalImage = false // Original full-frame image (default: false). // Configure UI element visibility. config.isCloseButtonVisible = true config.isTorchButtonVisible = true config.isCameraToggleButtonVisible = true config.isBeepButtonVisible = true config.isVibrateButtonVisible = true config.isFormatSelectorVisible = true config.isGuideFrameVisible = true // Configure feedback on a successful scan. config.isBeepEnabled = true config.isVibrateEnabled = false let vc = MRZScannerViewController() vc.config = config vc.onScannedResult = { [weak self] result in // Convert to UIImage here, or later from the result — either works. let portrait = try? result.getPortraitImage()?.toUIImage() let mrzSide = try? result.getDocumentImage(.mrz)?.toUIImage() let oppositeSide = try? result.getDocumentImage(.opposite)?.toUIImage() // The callback runs off the main thread and the scanner does not close // itself, so hop to the main queue and dismiss it here. DispatchQueue.main.async { self?.dismiss(animated: true) switch result.resultStatus { case .finished: // Scan completed successfully. data is nil for the other statuses. guard let data = result.data else { return } let mrzText = data.mrzText let firstName = data.firstName // Check a single field against its MRZ check digit. let status = data.getFieldValidationStatus("documentNumber") case .canceled: // The user closed the scanner before completing a scan. break case .exception: // An error occurred during initialization or scanning. let errorCode = result.errorCode let errorMessage = result.errorString @unknown default: break } } } // The scanner draws its own close button, so present it full screen. vc.modalPresentationStyle = .fullScreen present(vc, animated: true) } }
The example presents the scanner modally, which works in any app. Pushing it onto a UINavigationController also works — hide the navigation bar while it is on screen, since the scanner draws its own close button, and pop instead of dismissing. The ScanMRZ sample takes that route.