OCR Studio SDK for iOS Integration

This guide describes how an iOS developer can use our technologies to add document recognition functionality to their application.

GitHub Repository

SDK Contents

  • doc — documentation
  • Samples/Swift/OCRStudioSDKSample.xcodeproj — sample project launch file
  • OCRStudioSDKCore/lib/*.xcframework — universal static library for iOS devices and Simulators
  • OCRStudioSDKCore/wrap — wrapper for the C++ library
  • OCRStudioSDKCore/include — C++ header files for Objective-C interface
  • OCRStudioSDKCore/config/*.ocr — configuration files
  • OCRStudioSDK — Objective-C GUI files for interacting with the library

All source files can be modified as needed.

Integration Overview

The C++ library is delivered as an xcframework, containing binaries for multiple iOS architectures.

Since Swift cannot interact with C++ directly, the library is integrated through an Objective-C wrapper located in the wrap directory.

When building the project in Xcode, you must specify the paths to the wrapper headers (wrap) and library interface headers (include) via Header Search Paths.

The OCRStudioSDK directory contains helper Objective-C files that simplify interaction with the library from Swift.

Swift code accesses the public Objective-C interfaces via OCRStudioSDK-Bridging-Header.h, which must also be included in the project.

Integration Steps

  1. Move the OCRStudioSDK directory with source files from the SDK to your project, selecting Create Groups.
  2. Similarly, add the OCRStudioSDKCore/wrap directory with the wrapper, selecting Create Groups.
  3. Add the OCRStudioSDKCore/lib/*.xcframework framework in your project under General -> Frameworks, Libraries, and Embedded Content -> "+", with Do not embed.
  4. Move the OCRStudioSDKCore/data directory, selecting Create Folder References.
  5. Set Header Search Paths to include:
    • OCRStudioSDKCore/include
    • OCRStudioSDKCore/wrap/objcocrstudiosdk/include
    • OCRStudioSDKCore/wrap/objcocrstudiosdk/include_impl
  6. For Swift projects, add OCRStudioSDK/OCRStudioSDK-Bridging-Header.h to the Objective-C Bridging Header in project settings.

Project Structure Example

├── config
├── wrap
└── OCRStudioSDK
    ├── Core
    ├── Controller
    ├── Media
    └── OCRStudioSDK-Bridging-Header.h

Working with the Library

The typical workflow with the library is:

  1. Initialize the library and load the configuration file.
  2. Create session settings defining what should be recognized.
  3. Prepare the image for recognition (either in a loop for video stream or once for gallery images).
  4. Initialize a session and pass the image.
  5. Parse the recognition results.

The OCRStudioSDK module fully encapsulates the library logic, offering delegates and classes for convenience.

After adding the *-Bridging-Header.h, main classes are available: OCRStudioSDKViewController and OCRStudioSDKInstance.

To receive recognition results, implement the OCRStudioSDKViewControllerDelegate protocol and initialize the wrapper as follows:

// Initialize controller
let ocrController: OCRStudioSDKViewController = {
  let ocrController = OCRStudioSDKViewController(lockedOrientation: false, withTorch: false, withBestDevice: true)
  return ocrController
}()

Engine Initialization

override func viewDidLoad() {
  super.viewDidLoad()

  // Set delegate to receive recognition results
  ocrController.ocrDelegate = self

  // Initialize engine from the bundle
  DispatchQueue.main.async {
      let configPaths = Bundle.main.paths(forResourcesOfType: "ocr", inDirectory: "config")
      if configPaths.count == 1 {
        self.engineInstance.initializeEngine(configPaths[0])
      }
  }

  // Attach engine to controller
  self.ocrController.attachEngineInstance(self.engineInstance)
}

Presenting the Recognition Screen

func showocrViewController() {

  // Setting video_recognition session type
  ocrController.sessionParams().setSessionType("video_recognition")

  // Specify document types for recognition
  ocrController.sessionParams().setTargetGroupType("default")
  ocrController.sessionParams().addTargetMask("are.id.*")

  // Set session timeout in seconds
  ocrController.sessionParams().setOptionWithName("sessionTimeout", to: "5.0")

  // Present the recognition screen
  present(ocrController, animated: true, completion: {
    print("sample: ocrViewController presented")
  })
}

Handling Recognition Callbacks

func ocrViewControllerDidRecognize(_ result: OBJCOCRStudioSDKResult, from buffer: CMSampleBuffer?) {
  let resultRef = result.getRef()
  if resultRef.allTargetsFinal() {
    // Access text fields
    let item_it = target.itemsBegin("string")
    let item_end =  target.itemsEnd("string")
    while !item_it.isEqual(to: item_end) {
      print(item_it.item().name(), item_it.item().value())
      item_it.step()
    }

    // Access images
    let item_image_it = target.itemsBegin("image")
    let item_image_end =  target.itemsEnd("image")

    while !item_image_it.isEqual(to: item_image_end) {
      if item_image_it.item().hasImage() {
        let image = item_it.item().image().convertToUIImage()
      }
      item_image_it.step()
    }

    // Dismiss recognition screen
    dismiss(animated: true, completion: nil)
  }
}

func ocrViewControllerDidCancel() {
  dismiss(animated: true, completion: nil)
}

func ocrViewControllerDidStop(_ result: OBJCOCRStudioSDKResult) {
  // Here you can display fields in the same way as in ocrViewControllerDidRecognize
  dismiss(animated: true, completion: nil)
}

Memory Management

iOS runtime does not manage C++ memory. ARC/GC cannot access objects created in C++. Most library classes return pointers to heap-allocated objects. Responsibility for freeing memory lies with the developer.

The OCRStudioSDK module encapsulates memory management for recognition. When using the API directly, developers are responsible for memory cleanup.

Exception Handling

The library may throw exceptions of type ocrstudio::OCRStudioSDKException for invalid input, incorrect calls, or other errors. The OCRStudioSDK module handles exceptions internally; when using the API directly, developers must implement proper exception handling.

RFID Support

Our SDK implements the process of reading NFC chips from identity documents using the NFCPassportReader library, which uses the open-source OpenSSL library for data decryption and CoreNFC (a UIKit package for NFC reading). Use the example below to embed RFID reading. Our SDK can also be used to parse NFC passports and perform document authentication checks if your product configuration supports parsing such data.

Library

NFCPassportReader

Imports

import NFCPassportReader

Code

func readPassport(mrzKey: String) {
  let passportReader = PassportReader()

  // specify which data groups (Data Groups) from the chip need to be read
  let dataGroups : [DataGroupId] = [.COM, .SOD, .DG1, .DG2]

  Task {
    do {
      // mrzKey — is string in format <passport number><passport number checksum><date of birth><date of birth checksum><expiry date><expiry date checksum>
      let passportModel = try await passportReader.readPassport(
        mrzKey: mrzKey,
        tags: dataGroups)

      DispatchQueue.main.async {
        // successfully read the chip and can now work with the data
        debugPrint(passportModel.documentNumber)
      }
    } catch {
      debugPrint(error.localizedDescription)
    }
  }
}