As part of its structured data capabilities, the Genius Scan SDK is able to detect readable codes on documents. This enables you to get both a clean image of the document as well as structured data representing the readable codes present on the document. For instance, this may let you send a scanned document to the proper backend depending on a barcode present on the document.
We recommend using the Genius Scan SDK if you are building a barcode or qr-code scanning feature as part of a document acquisition process.
The following readable codes are supported:
In this guide, we will write a very simple barcode scanning app in a UIKit project. Writing this app should take about 10 minutes.
Add the Genius Scan SDK as a dependency to your project by following the section Integrating the framework from the Getting Started guide.
You will instantiate a scan flow with a specific configuration:
configuration.structuredData
to .readableCode
to specify you are interested in scanning 2D-codes.configuration.struturedDataReadableCodeTypes
to the readable codes you want to detect. By default, the SDK will attempt to detect any kind of supported code, but for better performane you should set this to only the code types you need.configuration.multiPage
to false
as generally you want the user to scan a single document and process it.skipPostProcessingScreen
to true
if you don’t need the user to review the document before processing it.let configuration = GSKScanFlowConfiguration()
configuration.structuredData = .readableCode
configuration.structuredDataReadableCodeTypes = [.ean13]
configuration.multiPage = false
configuration.skipPostProcessingScreen = true
You can now start the scan flow.
Note: The Genius Scan SDK offers multiple convenient ways of starting the scan flow, in particular from UIKit view controllers or from SwiftUI views.
// Keep a strong reference on ScanFlow
let scanFlow = GSKScanFlow(configuration: configuration)
do {
let result = try await scanFlow.resultByStarting(fromViewController: viewController)
handleResult(result)
} catch {
handleError()
}
We can now write the handleResult
method. Since this is a demo, we will just output the extracted data but in your real application you will likely display the data to the user for validation, and then serialize it to send it to your backend.
func handleResult(_ result: GSKScanFlowResult) {
// We only consider the first scan since we are in single-page mode
guard let scan = result.scans.first else {
print("Unexpected error")
return
}
// Check if there is structured data
guard let structuredResult = scan.structuredDataResult else {
print("No structured data result")
return
}
// Check if a receipt has been detected
guard let readableCodes = structuredResult.readableCodes else {
print("No readable codes detected")
return
}
for readableCode in readableCodes {
print("Type: \(readableCode.type)")
print("Value: \(readableCode.value)")
}
}
It’s important to handle the error as well, there are two important cases:
func handleError(_ error: Error) {
if (error as NSError).domain == GSKScanFlowErrorDomain && (error as NSError).code == GSKScanFlowError.userCancellation.rawValue {
// Do nothing
} else {
// Show a UIAlertController with error.localizedDescription
}
}
You can now build and run the application on an actual device (the iOS simulator doesn’t support the camera) to test the barcode scanning.
© 2025 The Grizzly Labs. All rights reserved.