Reader SDK Documents
Breadcrumbs

Novarum Reader SDK iOS Integration

1.1. Overview

The Novarum SDK for iOS enables iOS applications to capture and analyze lateral flow tests using the device’s camera.
It handles camera setup, test image capture, and analysis result generation, allowing you to focus on the interpretation and presentation of the test outcomes.

This guide describes how to integrate the SDK into an iOS project using CocoaPods, configure required permissions, and use the core reader view in a SwiftUI application.


1.2. Platform Configuration

1.2.1. Minimum Deployment Target

Platform

Minimum SDK Version

iOS

14.2

The SDK supports both UIKit and SwiftUI-based applications running on iOS 14.2 or later.


1.2.2. Access to the Private Pod Repository

The Novarum SDK is distributed through a private CocoaPods repository hosted on Bitbucket.
To install the SDK, you must configure SSH authentication for the provided Novarum Bitbucket account.

1.2.2.1. Requirements

  • Access to the NovarumDX Bitbucket account (credentials provided separately).

  • Git LFS installed (required, as the SDK uses Git LFS to store binary artifacts).

  • Access to CocoaPods (gem install cocoapods).

1.2.2.2. Steps

  1. Set up SSH credentials for Bitbucket following Bitbucket’s SSH key setup guide.

  2. Confirm connectivity:

    ssh -T git@bitbucket.org
    

    You should see a message confirming authentication.

  3. Ensure Git LFS is installed:

    git lfs install
    

1.3. Pod Repository Configuration

Add the Novarum private repository to your app’s Podfile.

source 'https://cdn.cocoapods.org/'
source 'git@bitbucket.org:novarum-dx/ndxpodlibrary-client.git'

Then add the required dependencies:

pod 'OpenCV2', '4.12.0'
pod 'NdxImagingSwift', '3.0.0'

💡 Note:
The OpenCV version has been updated to 4.12.0 to match the Android SDK and ensure algorithmic consistency across platforms.

Run pod install to fetch and integrate the specified SDK version.

pod install

After installation, open the generated .xcworkspace file to continue development.


1.4. Permissions Configuration

The SDK requires camera access for capturing test images.
Add the following entry to your app’s Info.plist file:

<key>NSCameraUsageDescription</key>
<string>We will use this for scans</string>

This message appears in the iOS system prompt when the app requests permission to use the camera.

Request camera permission before displaying the reader view.


1.5. Using the SDK

The iOS SDK provides a ReaderView SwiftUI component that manages the full camera and analysis workflow.
It can be easily embedded into a SwiftUI view hierarchy.


1.5.1. Loading the Analyser Configuration

Load the analyser configuration JSON file you were provided by Novarum:

let json = "..." // contents of your analyser configuration JSON
let analyserConfiguration = PMFLoader.loadAnalyserConfiguration(json: json)

Note:
The parameter name has been updated from jsonStringjson.


1.6. Using the Reader View (SwiftUI)

The ReaderViewWrapper is the primary SwiftUI component for embedding the Novarum reader experience within your app.
It manages the camera session, frame capture, and test analysis workflow.

1.6.1. Example Usage

@State private var progress: Double = 0.0
@State private var isAborted: Bool = false

ReaderViewWrapper(
    analyserConfiguration: analyserConfig,
    previewMode: .fill, // .fill or .fit
    onFrameCaptured: { callback in
        progress = Double(callback.progress)
    },
    onComplete: { model in
        // Handle completed analysis
    },
    onAbort: { model in
        // Handle abort event with collected data
    },
    isAborted: $isAborted
)

1.6.2. Parameter Overview

Parameter

Type

Description

analyserConfiguration

AnalyserConfiguration

The analyser configuration provided by Novarum. Defines test type, layout, and overlay behaviour.

previewMode

PreviewMode

Determines how the camera feed is scaled within the view. Available options:

  • .fill – fills the available view area (cropping if necessary)

  • .fit – fits entirely within the view while maintaining aspect ratio.

onFrameCaptured

(FrameCapturedCallback) -> Void

Invoked for each frame processed by the SDK. Useful for tracking progress, orientation, or brightness.

onComplete

(AnalysisModel) -> Void

Called when the analysis has successfully completed. Returns the full AnalysisModel.

onAbort

(AnalysisModel) -> Void

Called if the scan is aborted — either manually or via isAborted. Returns partial analysis data collected up to that point.

isAborted

Binding<Bool>

Setting this binding to true programmatically stops the reader process and triggers the onAbort callback. The SDK resets this value to false once handled.

1.6.3. Callback Data Structures

The SDK provides strongly typed models for both the frame-level and full-analysis callbacks.
These structures define the data returned by the onFrameCaptured, onComplete, and onAbort closures.

1.6.3.1. FrameCapturedCallback

public struct FrameCapturedCallback {
    public let progress: Float
    public let resultPMF: ResultPMF
    public let orientation: [Double]
    public let lux: Float
}

Description:

Property

Type

Description

progress

Float

Current scan progress, ranging from 0.0 to 1.0.

resultPMF

ResultPMF

Intermediate analysis result for the captured frame.

orientation

[Double]

Device orientation values as Euler angles.

lux

Float

Ambient light level measured during frame capture.

Typically used in onFrameCaptured to update progress indicators or monitor capture conditions.


1.6.3.2. AnalysisModel

public struct AnalysisModel: Encodable {
    public let testConfig: TestConfiguration
    public let testStrips: [TestStrip]
    public let pmfStory: [FrameData]
}

Description:

Property

Type

Description

testConfig

TestConfiguration

Contains test setup and processing parameters.

testStrips

[TestStrip]

Array of analysed test strips, each containing line scores and positions.

pmfStory

[FrameData]

Complete frame history captured during the analysis session.

Returned in the onComplete and onAbort callbacks, allowing your app to inspect or serialise the full analysis results.


1.6.4. Example Usage

onFrameCaptured: { callback in
    print("Progress: \(callback.progress * 100)% | Lux: \(callback.lux)")
}

onComplete: { model in
    print("Test strips detected: \(model.testStrips.count)")
    print("First C-line score: \(model.testStrips.first?.cLine?.score ?? 0)")
}

The following supporting models are included within the AnalysisModel and FrameCapturedCallback objects.

Type

Kind

Description

ResultPMF

enum

Indicates the fit result for a processed frame (fit, marginalFit, or noFit).

TestStrip

struct

Represents a single test strip, including control and test line data.

CLine

struct

The control line model, containing score, peak position, and area.

TLine

struct

A test line model, containing score, T/C ratio, peak position, and area.

FrameData

struct

Frame-level capture metadata, including light level, orientation, and baseline/profile data.

StripStatus

enum

Indicates strip state during capture (none, good, done, exposureError, baselineError).

For detailed property definitions, see the generated documentation in your Swift IDE (⌘ + click on type names).


1.6.6. Behaviour Notes

  • When isAborted is toggled to true, the reader immediately halts scanning, performs cleanup, and invokes onAbort.

  • When previewMode is set to .fit, the entire camera preview will remain visible without cropping — suitable for UI layouts where the full frame must be shown.
    .fillremains the default and ensures edge-to-edge display for most use cases.

💡 Tip: Combine isAborted with your app’s state management to implement user-triggered aborts or automatic cancellation (e.g., timeout scenarios).


1.6.7. Optional: SVG Overlay Visualisation

If your analyser configuration supports SVG overlay visualisation, the SDK will render overlays using high-resolution, scalable SVGs instead of the default dotMatrix mode.

  • Default mode: dotMatrix

  • To enable: Request an updated configuration file from your Novarum representative.

No code changes are required — the visualisation mode is determined by the configuration JSON.


1.7. Troubleshooting

Issue

Possible Cause

Resolution

Permission Denied when accessing the private repo

SSH key not configured

Add SSH key to Bitbucket and verify with ssh -T git@bitbucket.org.

Missing OpenCV2 dependency

Podfile missing OpenCV

Add pod 'OpenCV2', '4.12.0' and rerun pod install.

Build fails with “code signing” errors

Missing Novarum certificate

Run bundle exec fastlane match --readonly to sync credentials.

Camera not activating

Missing Info.plist permission

Ensure NSCameraUsageDescription is set correctly.

Overlays not matching Android visuals

Outdated configuration file

Request updated SVG-enabled configuration from Novarum.


1.8. Version Compatibility Summary

Component

Version

Notes

Novarum iOS SDK

v3.0.0

Current release

Minimum iOS SDK

14.2

Required

OpenCV

4.12.0

Matches Android SDK

Analyser Config API

loadAnalyserConfiguration(json:)

Unified parameter naming

SVG Visualisation

Optional

Enabled via updated config

Distribution

Private CocoaPods (Bitbucket)

SSH & Git LFS required


1.9. Support

For access credentials, configuration files, or integration assistance, please contact your Novarum support representative or technical account manager.