Skip to main content

IOS Integration

Please follow these steps for integrating OCR Lite xcframework.

note

You can find sample project containing complete integration of SDK here (requires access).

Integration Guide (Swift)​

You can add the OcrLite framework to your project using either CocoaPods.

Pods Linking​

For linking OcrLite library using CocoaPods you can add either:

  • OcrLite repository link with version tag in your Podfile
pod 'Ocr', :git => "https://gitlab.com/fetchsky/peekaboo-connect-studio/identity/ocr-lite-pod", :tag => "vX.X.X"

Use the latest communicated version of the framework.

  • Or place OcrLite directory in your project root and its path in your Podfile
pod 'Ocr', :path => "./OcrLite"

Run pod install in your terminal.

Using Library​

Link Ocr in your ViewController

import Ocr

Conform to OcrControllerDelegate protocol in your class to handle events and results related to the framework.

class ViewController: OcrControllerDelegate { ....

Initialize OcrViewController​

Create an instance of OcrViewController with the CNIC number to validate against. See Initialization Parameters for the full list of supported parameters.

let ocrController = OcrViewController(cnicNumber: "your_cnic_number")

Setup and Display​

Set the delegate and present the controller modally:

// Set Delegate
ocrController.delegate = self

// Show the scanner full screen (the iOS default is a page sheet)
ocrController.modalPresentationStyle = .fullScreen

// Present the scanner
present(ocrController, animated: true)

Launch Landscape UI​

The SDK also ships a full-screen landscape scanner, OcrLandscapeViewController. It is a subclass of OcrViewController, takes the same initialization parameters and calls the same OcrControllerDelegate methods.

Present it modally, as with the portrait scanner. Do not add it as a child view controller. The controller locks the interface to landscape, and iOS applies an orientation lock only to a presented controller.

var ocrController: OcrViewController? = nil

func launchLandscape() {
let controller = OcrLandscapeViewController(
cnicNumber: "your_cnic_number",
skipProcessing: false,
blurThreshold: 100,
imageWidth: 1000,
showBranding: false,
scanMode: "frontAndBack" // "frontAndBack", "frontOnly", "backOnly"
)
controller.delegate = self
ocrController = controller
present(controller, animated: true)
}

The controller always presents full screen (its modalPresentationStyle is fixed to .fullScreen), opens in landscape right, and hides the status bar and home indicator. The camera fills the screen, the area outside the card holder is blurred and dimmed, and only the card holder region is classified and saved.

Allow landscape orientations in your app. The target's supported interface orientations must include Landscape Left and Landscape Right (Xcode: target ▸ General ▸ Deployment Info ▸ iPhone Orientation, or UISupportedInterfaceOrientations in Info.plist). Your other screens can stay portrait: override supportedInterfaceOrientations in their view controllers to return .portrait.

warning

If your app supports portrait only, iOS cannot rotate to landscape and the presentation fails with an UIApplicationInvalidInterfaceOrientation exception. If your AppDelegate implements application(_:supportedInterfaceOrientationsFor:), it must also return a mask that includes landscape.

Closing the Scanner​

The portrait and landscape scanners close the same way:

  • Close button: when the user taps it, the controller dismisses itself and calls handleInfo(message: "Ocr closed"). Do not dismiss it again.
  • Result or error: after handleResponse or handleError, the SDK does not close itself. Call dismiss(animated: true) in your delegate method.

Event Handlers​

Implement the required delegate methods:

class ViewController: OcrControllerDelegate {

func handleInfo(message: String) {
// Informational messages: "Ocr initialized", "Ocr closed" (user tapped close)
print("Info: \(message)")
}

func handleError(code: String) {
// Camera unavailable or could not be configured.
// The current SDK version sends the code "no_camera".
print("Error: \(code)")

// Dismiss the scanner when an error occurs
dismiss(animated: true)
}

func handleResponse(identityNumber: String?, frontImage: String, backImage: String, documentType: DocumentType, distance: Double, extractedData: ExtractedData) {
// Handle successful OCR response
// identityNumber: CNIC number read from the back-card barcode (nil for "frontOnly" scans)
// frontImage: Base64 encoded JPEG of the front image (empty for "backOnly" scans)
// backImage: Base64 encoded JPEG of the back image (empty for "frontOnly" scans)
// documentType: .new (chip-based) or .old
// distance: 0 when identityNumber matches the cnicNumber passed at launch, otherwise 1
// extractedData: Structured fields parsed from the front card by the SDK
// (see the extractedData fields below). Empty when nothing
// could be recognized or parsed — it never throws.

print("Identity Number: \(identityNumber ?? "-")")
print("Document Type: \(documentType)")
print("Distance: \(distance)")
print("Extracted Data: \(extractedData.toDictionary())")

// Dismiss the scanner after successful processing
dismiss(animated: true)
}
}

To display a returned image, decode the Base64 string:

if let data = Data(base64Encoded: frontImage), let image = UIImage(data: data) {
imageView.image = image
}

Extracted Data​

extractedData is an ExtractedData value parsed by the SDK from the front card using on-device text recognition (Apple Vision). It is populated for new (chip-based) CNICs only; old cards have no machine-readable text fields and yield an empty value. All parsed fields are optional String? — a field that could not be recognized is left nil, and a fully failed recognition yields an empty value (it never throws). The raw field holds the complete unparsed text as recognized and is populated whenever any text was recognized, even when no individual field could be parsed. Call toDictionary() to get only the populated fields as a [String: String].

public struct ExtractedData {
public var name: String?
public var fatherName: String?
public var identityNumber: String?
public var dateOfBirth: String? // DD.MM.YYYY
public var dateOfIssue: String? // DD.MM.YYYY
public var dateOfExpiry: String? // DD.MM.YYYY
public var gender: String? // "M" | "F" | "X"
public var country: String?
public var raw: String? // Full unparsed OCR text (present whenever any text was recognized)

public func toDictionary() -> [String: String]
}

See the extractedData object reference for a description of each field.

Complete Implementation Example​

class ViewController: UIViewController, OcrControllerDelegate {

var ocrController: OcrViewController? = nil

@IBAction func launchOCR(_ sender: Any) {
let controller = OcrViewController(cnicNumber: "your_cnic_number")
controller.delegate = self
controller.modalPresentationStyle = .fullScreen
ocrController = controller
present(controller, animated: true)
}

@IBAction func launchLandscapeOCR(_ sender: Any) {
let controller = OcrLandscapeViewController(cnicNumber: "your_cnic_number")
controller.delegate = self
ocrController = controller
present(controller, animated: true)
}

// Implement delegate methods as shown above
}

Updating Info.plist​

Add Privacy - Camera Usage Description in your app's Info.plist to allow access to camera.