This page covers the iOS migration from SDK 5.17.x to SDK 6.0.0-beta11.
GSKCameraViewController API, its delegate callbacks, and its camera view properties.Use this section if your app launches the SDK-provided scan flow or barcode scan flow. Start with the iOS requirements; they apply to every iOS SDK 6 integration, including custom integrations.
6.0.0-beta11.https://github.com/thegrizzlylabs/geniusscan-sdk-spm and change its version requirement from the v5 series to 6.0.0-beta11.SDK 6 aligns scan-flow error categories across platforms. Native Swift code can catch GSKScanFlowError and inspect its code.
| Error code | Meaning |
|---|---|
GSKScanFlowErrorCode.cancellation |
The user canceled the scan flow. |
GSKScanFlowErrorCode.configuration |
The scan flow was launched with invalid or unsupported configuration. |
GSKScanFlowErrorCode.licensing |
The license is invalid, expired, or not initialized. |
GSKScanFlowErrorCode.capture |
The camera or capture flow failed. |
GSKScanFlowErrorCode.storageSpace |
The device does not have enough storage space to complete the flow. |
GSKScanFlowErrorCode.internal |
The SDK hit an unexpected error. |
Treat cancellation as a normal user action:
do {
let result = try await flow.resultByStarting(fromViewController: viewController)
} catch let error as GSKScanFlowError where error.code == .cancellation {
return
}
Use error.underlyingError when you need to inspect the original lower-level error. See GSKScanFlowError and GSKScanFlowErrorCode for the complete API.
If your app uses the standalone readable-code scanner, migrate it to the barcode flow. The flow, configuration, result, model, and type names now use barcode terminology.
| SDK 5 | SDK 6 |
|---|---|
GSKReadableCodeFlow |
GSKBarcodeScanFlow |
GSKReadableCodeFlowConfiguration |
GSKBarcodeScanFlowConfiguration |
GSKReadableCodeFlowResult.readableCodes |
GSKBarcodeScanFlowResult.barcodes |
GSKStructuredDataReadableCode |
GSKBarcode |
Before:
let configuration = GSKReadableCodeFlowConfiguration(
supportedCodeTypes: [.qr, .code128],
isBatchModeEnabled: true
)
let flow = GSKReadableCodeFlow(configuration: configuration)
let result = try await flow.resultByStarting(fromViewController: viewController)
let codes = result.readableCodes
After:
let configuration = GSKBarcodeScanFlowConfiguration(
supportedCodeTypes: [.qr, .code128],
isBatchModeEnabled: true
)
let flow = GSKBarcodeScanFlow(configuration: configuration)
let result = try await flow.resultByStarting(fromViewController: viewController)
let codes = result.barcodes
For supported code types, use GSKBarcodeType.
If your document scan flow extracts readable codes as structured data, update that configuration to barcode terminology as well.
Before:
let configuration = GSKScanFlowConfiguration()
configuration.structuredData = [.receipt, .readableCode]
configuration.structuredDataReadableCodeTypes = [.qr, .code128]
if let result = scan.structuredDataResult {
let codes = result.readableCodes
}
After:
let configuration = GSKScanFlowConfiguration()
configuration.structuredData = [.receipt, .barcode]
configuration.structuredDataBarcodeTypes = [.qr, .code128]
if let result = scan.structuredData {
let codes = result.barcodes
}
Dictionary-based configuration remains backward compatible for readableCode and structuredDataReadableCodeTypes, and result dictionaries still include the legacy readableCodes key. Treat those aliases as migration support and move new code to barcode, structuredDataBarcodeTypes, and barcodes. The full configuration surface is documented in GSKScanFlowConfiguration.
The Swift enum cases for multi-page document output now use lower camel case:
// SDK 5
configuration.multiPageFormat = .PDF
// SDK 6
configuration.multiPageFormat = .pdf
The same applies to .TIFF, which becomes .tiff. See GSKScanFlowMultiPageFormat for the complete enum.
Use this section if your app embeds the SDK camera or lower-level scanning components instead of launching the SDK-provided scan flow. The iOS requirements from the Simple Integration section still apply.
SDK 6 rebuilds the public custom camera API around GSKCameraViewController. Do not create or pass a public GSKCameraSession anymore.
Before:
let configuration = GSKCameraSessionConfiguration()
let cameraSession = GSKCameraSession(configuration: configuration)
let cameraViewController = CameraViewController(cameraSession: cameraSession)
After:
let cameraViewController = try await CameraViewController()
final class CameraViewController: GSKCameraViewController {
init() async throws {
try await super.init(configuration: .documentDetection())
}
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
}
}
Because the initializer is async and can throw, create the camera controller from an async context and handle initialization failures before presenting it. For example, a parent view controller can show a loading state, then replace it with either the camera controller or an error view controller:
final class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
Task { @MainActor in
do {
let cameraViewController = try await CameraViewController()
setContentViewController(cameraViewController)
} catch {
let errorViewController = ErrorViewController(error: error)
setContentViewController(errorViewController)
}
}
}
}
If you create the camera from Objective-C, use the async factory method instead of a direct initializer:
[GSKCameraViewController makeCameraViewControllerWithDocumentDetectionMode:YES
documentOverlayColor:nil
completionHandler:^(GSKCameraViewController *controller, NSError *error) {
// Present the controller or handle the error.
}];
See GSKCameraViewController for the complete custom camera API.
Move camera session overrides to GSKCameraViewControllerDelegate.
| SDK 5 callback | SDK 6 callback |
|---|---|
cameraSession(_:didGenerateScan:) |
cameraViewController(_:didGenerateScan:) |
cameraSessionFailedToFindQuadrangle(_:) |
cameraViewControllerFailedToFindDocument(_:) |
cameraSession(_:didFindQuadrangle:) |
cameraViewController(_:didFindDocumentWithQuadrangle:) |
cameraSessionIsAboutToChooseQuadrangle(_:) |
cameraViewControllerPhotoStabilizationDidStart(_:) |
cameraSession(_:willAutoTriggerWithQuadrangle:) |
cameraViewController(_:willSnapPhotoWithQuadrangle:) |
Example:
extension CameraViewController: GSKCameraViewControllerDelegate {
func cameraViewController(_ cameraViewController: GSKCameraViewController, didGenerateScan scan: GSKScan) {
// Handle the generated scan.
}
}
See GSKCameraViewControllerDelegate for the complete delegate surface.
The public camera view is now exposed as cameraView instead of captureView. Configure document overlay color through GSKCameraViewController.Configuration.documentDetection(overlayColor:), and toggle auto capture through documentDetectionMode on the view controller:
cameraViewController.documentDetectionMode = .highlightAndAutoCapture
cameraViewController.documentDetectionMode = .highlightOnly
SDK 6 also exposes pause(), resume(), showShutterView(), hideShutterView(), flashStatus, and photoStabilizationDuration on GSKCameraViewController.
If your app detects barcodes directly, outside of GSKScanFlow, rename the detector and model types.
Before:
let codes = try await GSKReadableCodeDetector().detectReadableCodes(
inFileAt: imageURL,
codeTypes: GSKStructuredDataReadableCodeType.allCases
)
After:
let barcodes = try await GSKBarcodeDetector().detectBarcodes(
inFileAt: imageURL,
codeTypes: GSKBarcodeType.allCases
)
See GSKBarcodeDetector for the detector API.
The OCR method now uses the generic configuration: parameter label instead of ocrConfiguration:.
Before:
let ocrResult = try await GSKOCR().recognizeText(
forImageAtPath: filePath,
ocrConfiguration: ocrConfiguration,
onProgress: { progress in
print("OCR engine progress: \(progress)")
}
)
After:
let ocrResult = try await GSKOCR().recognizeText(
forImageAtPath: filePath,
configuration: ocrConfiguration,
onProgress: { progress in
print("OCR engine progress: \(progress)")
}
)
See GSKOCR for the complete OCR API.
The PDF document generator configuration factory was renamed.
Before:
try GSKDocumentGenerator().generate(
document,
configuration: .pdfConfiguration(withOutputFilePath: outputFilePath)
)
After:
try GSKDocumentGenerator().generate(
document,
configuration: .pdf(outputFilePath: outputFilePath)
)
See GSKDocumentGeneratorConfiguration for available document output factories.
When configuring GSKEditFrameViewController, set the magnifier center style through the view controller property instead of reaching into the internal frame view.
Before:
frameView.magnifierView.centerStyle = .quadrangle
After:
magnifierViewCenterStyle = .quadrangle
See GSKEditFrameViewController for the edit-frame API.
After applying the sections that match your integration, build your app with SDK 6 and run through the scan paths your users rely on.
For simple integrations, validate scan-flow presentation, barcode scan presentation, success results, cancellation, licensing failures, and any custom error UI built from GSKScanFlowError. If your app extracts barcodes as structured data or generates multi-page output, check those result fields and files against your SDK 5 behavior.
For custom integrations, validate the async camera-controller initialization path, including the catch path that presents an error state. Also check camera startup, capture, auto-capture behavior, delegate callbacks, direct barcode detection, OCR, document generation, and edit-frame UI if your app uses them.
Start with a free trial license to test the SDK, or contact us directly for a custom quote tailored to your needs.
© 2026 The Grizzly Labs. All rights reserved.