---
title: Use Case Examples
description: SmartSpectra Swift examples for metrics, face landmarks, custom camera and decoded video input, data export, and iOS UI state.
sidebarTitle: Use Case Examples
---

> SmartSpectra SDK developer docs for v3.4.0, the latest stable release. Web page: https://presagetech.com/docs/smartspectra-sdk/swift/use-case-examples
> Index of all pages: https://presagetech.com/docs/smartspectra-sdk/llms.txt

# iOS Use Case Examples

These are intentionally short, partial examples. They are meant to show one pattern at a time, not serve as complete drop-in apps.

## Shared Setup

Most examples assume you already own an SDK instance:

```swift
import SwiftUI
import AVFoundation
import Charts
import SmartSpectra

struct ExampleHostView: View {
    private let sdk = SmartSpectraSDK.shared

    init() {
        sdk.config.apiKey = "YOUR_API_KEY"
    }

    var body: some View {
        Text("Ready")
    }
}
```

## Accessing Face Mesh

Read the latest face landmarks from `sdk.metrics` and render them into your own overlay.
Face landmarks are only populated when face metrics are requested.

Landmarks are **pixel coordinates in the capture frame**, so scale `x` by the frame
width and `y` by the frame *height* — they are different numbers. Capture defaults to
1280x720; if you change the capture resolution, change these constants to match.

```swift
let captureWidth: CGFloat = 1280
let captureHeight: CGFloat = 720

sdk.config.requestedMetrics = SmartSpectraConfig.breathingMetrics + SmartSpectraConfig.faceMetrics

if let latestLandmarks = sdk.metrics?.face.landmarks.last {
    GeometryReader { geometry in
        ZStack {
            ForEach(Array(latestLandmarks.value.enumerated()), id: \.offset) { _, landmark in
                Circle()
                    .fill(.blue)
                    .frame(width: 3, height: 3)
                    .position(
                        x: CGFloat(landmark.x) * geometry.size.width / captureWidth,
                        y: CGFloat(landmark.y) * geometry.size.height / captureHeight
                    )
            }
        }
    }
}
```

## Accessing Metrics

Read the latest metrics directly from the SDK object.
Pulse and HRV values require cardio metrics to be requested.

```swift
sdk.config.requestedMetrics = SmartSpectraConfig.breathingMetrics + SmartSpectraConfig.cardioMetrics

if let metrics = sdk.metrics {
    if let breathingRate = metrics.breathing.rate.last {
        Text("Breathing: \(breathingRate.value.formatted()) RPM")
    }

    if let pulseRate = metrics.cardio.pulseRate.last {
        Text("Pulse: \(pulseRate.value.formatted()) BPM")
    }
}
```

## LineChartView

Use a small reusable chart view for breathing, pulse, or confidence values.

```swift
struct LineChartView: View {
    let orderedPairs: [(time: Date, value: Float)]
    let title: String

    var body: some View {
        VStack(alignment: .leading) {
            Text(title)
                .font(.headline)

            Chart {
                ForEach(orderedPairs, id: \.time) { pair in
                    LineMark(
                        x: .value("Time", pair.time),
                        y: .value("Value", pair.value)
                    )
                }
            }
            .frame(height: 180)
        }
    }
}
```

You can feed it from metrics like this:

```swift
if let breathingSeries = sdk.metrics?.breathing.rate {
    LineChartView(
        orderedPairs: breathingSeries.map {
            (
                time: Date(timeIntervalSince1970: Double($0.timestamp) / 1_000_000.0),
                value: $0.value
            )
        },
        title: "Breathing Rate"
    )
}
```

## Metrics Data Export

Convert the latest metrics into your own export format before writing to disk or uploading.

```swift
struct MetricsExportRow: Codable {
    let timestampUs: Int64
    let breathingRate: Float?
    let pulseRate: Float?
}

if let metrics = sdk.metrics {
    let row = MetricsExportRow(
        timestampUs: metrics.breathing.rate.last?.timestamp
            ?? metrics.cardio.pulseRate.last?.timestamp
            ?? 0,
        breathingRate: metrics.breathing.rate.last?.value,
        pulseRate: metrics.cardio.pulseRate.last?.value
    )

    let jsonData = try JSONEncoder().encode(row)
    let jsonString = String(decoding: jsonData, as: UTF8.self)
    print(jsonString)
}
```

## State Management

Own the SDK once and bind UI directly to its observable state.

```swift
struct MonitoringView: View {
    private let sdk = SmartSpectraSDK.shared

    init() {
        sdk.config.apiKey = "YOUR_API_KEY"
    }

    var body: some View {
        VStack {
            Text("Status: \(String(describing: sdk.processingStatus))")

            if let validationStatus = sdk.validationStatus {
                Text(validationStatus.hint)
            }

            if let error = sdk.error {
                Text(error.message)
                    .foregroundStyle(.red)
            }
        }
    }
}
```

## Camera Handling

For SDK-owned capture, select the camera while stopped before calling
`try await sdk.start()`.

```swift
let sdk = SmartSpectraSDK.shared

sdk.config.apiKey = "YOUR_API_KEY"
try sdk.useCamera(.front)
```

To change cameras, stop, select the camera, and start again. Explicit selections
never fall back to another camera.

```swift
@MainActor
func switchToBackCamera() async throws {
    let sdk = SmartSpectraSDK.shared
    try await sdk.stop()
    try sdk.useCamera(.back)
    try await sdk.start()
}
```

## Your Own Camera or Video Decoder

If your app already captures video, select `try sdk.useCustomInput()` while
stopped, await `sdk.start()`, and pass each uncompressed sample to
`input.sendFrame(sampleBuffer)`. Handle `.rejected(let error)` and observe
metrics as above. Your app keeps ownership of its camera and buffers.

The [AVFoundation example](headless-mode.md#use-your-own-camera-or-video-source)
shows capture delegation and buffer requirements. The demo app's
[Video Testing sample](https://github.com/Presage-Security/SmartSpectra/blob/main/swift/samples/demo-app/VideoInput/VideoTestingView.swift)
uses `AVAssetReader` to decode a clip and submit its frames through the public
API, including cancellation, frame rejection, and cleanup. Both paths require
normal SDK authentication.
