Capture UI
Pre-built SwiftUI and UIKit views for the complete capture experience with full theming.
Capture Session
Core orchestrator for camera, pose detection, leveling, and recording.
Scan Client
Upload scans, retrieve measurements, health reports, and body fat analysis.
Data Models
Scan, Measurements, HealthReport, User, and shared types.
Module Architecture
// Dependency direction: PrismUI -> PrismKit -> PrismLink
PrismUI SwiftUI views, theming, audio guidance
PrismSessionView SwiftUI entry point
PrismSessionViewController UIKit entry point
PrismThemeConfiguration Colors, fonts, icons
PrismKit Camera, pose detection, state machine, recording
CaptureSession Main orchestrator
CaptureSessionState Flow state enum
PrismStateManager Protocol for step managers
PrismLink REST API client, models
ScanClient Scan CRUD, measurements, health
UserClient User management
ApiClient Base HTTP client
public struct PrismSessionView: View
Provides the entire capture experience — volume check, device leveling, face guidance, body positioning, A-pose validation, recording, and completion — as a single SwiftUI view with voice guidance and sound effects.
Initializer
public init(
receivedArchive: @escaping (URL) -> Void,
onStatus: @escaping (CaptureSessionState) -> Void,
onDismiss: @escaping () -> Void
)
| Parameter | Type | Description |
| receivedArchive | (URL) -> Void | Called with the file URL of the recording zip archive when capture completes. |
| onStatus | (CaptureSessionState) -> Void | Called on each capture state change. Useful for analytics. |
| onDismiss | () -> Void | Called when the session view is dismissed. |
Environment Values
| Key | Type | Description |
| \.enableFaceGuidance | Bool | Enables face guidance step. Default: false. |
| \.useScanReview | Bool | Shows scan review screen before completing. Default: false. |
| \.prismThemeConfiguration | PrismThemeConfiguration | Theme for colors, fonts, and icons. |
Usage
PrismSessionView(
receivedArchive: { url in
print("Archive: \(url)")
},
onStatus: { _ in },
onDismiss: {}
)
.environment(\.enableFaceGuidance, true)
.applyTheme(.default)
public class PrismSessionViewController: UIViewController
Initializer
public init(
theme: PrismThemeConfiguration = .default,
delegate: PrismSessionViewControllerDelegate? = nil
)
| Parameter | Type | Description |
| theme | PrismThemeConfiguration | Theme configuration. Defaults to .default. |
| delegate | PrismSessionViewControllerDelegate? | Delegate for capture callbacks. |
Usage
let vc = PrismSessionViewController(
theme: .default,
delegate: self
)
vc.modalPresentationStyle = .fullScreen
present(vc, animated: true)
public protocol PrismSessionViewControllerDelegate: AnyObject
Required Methods
| Method | Description |
| prismSession(_:didRecieveArchive:) | Called when capture completes with the archive file URL. |
| prismSession(_:didChangeStatus:) | Called on each state change. Use for analytics. |
| prismSession(willDismiss:) | Called before dismissal. You must call controller.dismiss(animated:). |
Signatures
func prismSession(
_ controller: PrismSessionViewController,
didRecieveArchive archive: URL
)
func prismSession(
_ controller: PrismSessionViewController,
didChangeStatus status: CaptureSessionState
)
func prismSession(
willDismiss controller: PrismSessionViewController
)
public struct PrismThemeConfiguration
Static Properties
| Property | Type | Description |
| .current | PrismThemeConfiguration | Currently applied theme singleton. |
| .default | PrismThemeConfiguration | Default Prism theme. |
Color Properties
| Property | Type | Description |
| primaryColor | Color | Primary brand color |
| secondaryColor | Color | Secondary brand color |
| tertiaryColor | Color | Tertiary accent color |
| successColor | Color | Success states |
| errorColor | Color | Error states |
| backgroundColor | Color | Primary background |
| secondaryBackgroundColor | Color | Secondary background |
| overlayColor | Color | Overlay/dimming |
| borderColor | Color | Border color |
| disabledColor | Color | Disabled states |
Text & Font Properties
| Property | Type | Description |
| titleTextColor | Color | Title text color |
| textColor | Color | General text color |
| buttonTextColor | Color | Button text color |
| largeTitleFont | Font | Large title font |
| titleFont | Font | Title font |
| secondaryTitleFont | Font | Secondary title font |
| bodyFont | Font | Body text font |
Component Properties
| Property | Type | Description |
| primaryButtonCornerRadius | CGFloat | Primary button corners (default: 12) |
| smallButtonCornerRadius | CGFloat | Small button corners (default: 12) |
| cardCornerRadius | CGFloat | Card/alert corners (default: 12) |
| sheetCornerRadius | CGFloat | Bottom sheet corners (default: 12) |
View Modifiers
// Apply full theme
.applyTheme(myTheme)
// Apply individual properties
.theme(\.primaryColor, .blue)
.theme(\.bodyFont, .custom("Avenir", size: 16))
public class CaptureSession: ObservableObject
Coordinates the entire capture pipeline: camera management, pose detection, device leveling, and recording. Publishes reactive state updates via Combine @Published properties.
Type Properties
| Property | Type | Description |
| isSupported | Bool | Whether the device supports body scanning (requires TrueDepth camera). |
Published Properties
| Property | Type | Description |
| state | CaptureSessionState | Current capture flow state. |
| states | [CaptureSessionState] | Remaining states in the flow. |
| permissions | CameraPermissionStatus | Camera permission status. |
| currentRecording | PrismRecording? | Completed recording data. |
| cameraBuffer | CameraBuffer? | Current camera frame buffer. |
| poses | [Pose]? | Detected body poses. |
| annotatedFrame | CGImage? | Frame with pose skeleton overlay. |
| levelState | PrismState | Device leveling state. |
| levelResult | MotionDetector.Level | Current device level. |
| verticalRotation | Double | Device vertical rotation angle. |
| positioningState | PrismState | Body positioning state. |
| positioningResult | DetectionFeedback? | Body positioning feedback. |
| posingState | PrismState | A-pose validation state. |
| posingResult | DetectionFeedback? | Pose validation feedback. |
| recordingState | PrismState | Recording state. |
| recordingCountDown | Int | Countdown timer value. |
| recordingUrl | URL? | Output recording file path. |
| faceGuidanceState | FacePositionManagerState | Face guidance state. |
Instance Properties
| Property | Type | Description |
| configuration | CaptureSessionConfiguration | Session configuration. |
| faceGuidanceEnabled | Bool | Whether face guidance is enabled. |
Methods
| Method | Description |
| start() async throws | Initialize and start the capture session. |
| stop() async throws -> URL | Finalize recording and return archive path. |
| cancel() async throws | Cancel the entire session. |
| checkAndContinue(from:start:) | Check if current state is complete and advance. |
| continue(from:shouldStart:) | Advance to the next state. |
| startStep() | Begin processing the current step. |
public class PrismCaptureSession: ObservableObject
Properties
| Property | Type | Description |
| session | CaptureSession | The underlying capture session. |
Initializer
public init(configuration: CaptureSessionConfiguration = .init())
public struct CaptureSessionConfiguration
Properties
| Property | Type | Description |
| poseTheme | PoseTheme | Skeleton visualization theme. |
| recordingMode | RecordingMode | .frames or .video. |
Initializer
public init(poseTheme: PoseTheme = .default, recordingMode: RecordingMode = .video)
@frozen public enum CaptureSessionState: Identifiable, Equatable, Hashable
Cases
| Case | Description |
| .idle | Initial/waiting state. |
| .volume | Volume setup step. |
| .faceGuidance | Face capture guidance (optional). |
| .leveling | Device leveling step. |
| .positioning | Body positioning step. |
| .posing | A-pose verification step. |
| .recording | Active recording. |
| .processing | Archive finalization. |
| .finished | Session complete. |
| .failed(Error) | Error state. |
@frozen public enum PrismState: Equatable, Hashable, Identifiable, CaseIterable
Cases
| Case | Description |
| .idle | Not running. |
| .running | Actively processing. |
| .finished | Processing complete. |
public protocol PrismStateManager
Required Properties
| Property | Type | Description |
| waitTime | TimeInterval | Hold time before auto-advancing. |
| state | PrismState | Current manager state. |
Required Methods
| Method | Description |
| start() | Begin processing. |
| stop() | Halt and mark finished. |
@frozen public enum CaptureError: Error
Cases
| Case | Description |
| .unsupportedDevice | No TrueDepth camera. |
| .invalidDocumentDirectory | Cannot access documents directory. |
| .invalidRecording | Recording state error. |
| .videoURLEmpty | Video file not created. |
@frozen public enum CameraPermissionStatus: Identifiable, CaseIterable
Cases
| Case | Description |
| .notDetermined | Not yet requested. |
| .restricted | Restricted by parental controls. |
| .denied | User denied access. |
| .authorized | User granted access. |
public final class ApiClient: ObservableObject, Sendable
Handles HTTP communication with the Prism backend. Loads configuration from PrismSDK-Info.plist by default.
Initializer
public init(
baseURL: URL? = nil,
clientCredentials: ApiClientBearerToken? = nil
)
| Parameter | Type | Description |
| baseURL | URL? | API base URL. Defaults to plist value. |
| clientCredentials | String? | Bearer token. Defaults to plist value. |
public struct ScanClient: Sendable
Initializer
public init(client: ApiClient)
Scan Methods
| Method | Description |
| createScan(_:) async throws -> Scan | Create a new scan record. |
| getScan(forScan:unitSystem:) async throws -> Scan | Fetch a scan by ID. |
| getScans(forUser:limit:cursor:order:unitSystem:) async throws -> Paginated<Scan> | Fetch paginated scans. |
| deleteScan(_:) async throws -> Scan | Delete a scan. |
Upload Methods
| Method | Description |
| uploadUrl(forScan:) async throws -> UploadUrl | Get presigned upload URL. |
| assetUrls(forScan:) async throws -> AssetUrls | Fetch all asset URLs. |
| assetUrl(forScan:option:) async throws -> String | Fetch a specific asset URL. |
Results Methods
| Method | Description |
| measurements(forScan:unitSystem:) async throws -> Measurements | Fetch body measurements. |
| getBodyFat(forScan:unitSystem:) async throws -> Bodyfat | Fetch body fat data. |
| updateBodyFatMethod(forScan:_:unitSystem:) async throws -> Bodyfat | Update body fat method. |
| getHealthReport(forScan:unitSystem:) async throws -> HealthReport | Fetch health report. |
| createBodyShapePrediction(_:unitSystem:) async throws -> BodyShapePrediction | Create body shape prediction. |
| getBodyShapePrediction(forBodyShapePrediction:unitSystem:) async throws -> BodyShapePrediction | Fetch prediction status. |
public struct UserClient: Sendable
Initializer
public init(client: ApiClient)
Methods
| Method | Description |
| create(user:) async throws -> User | Create or upsert a user. |
| update(user:) async throws -> User | Update an existing user. |
| fetchUser(for:unitSystem:) async throws -> User | Fetch user by token. |
Scan
public struct Scan: Codable, Sendable
| Property | Type | Description |
| id | String | Unique scan identifier. |
| userId | String | Associated user ID. |
| userToken | String | User token. |
| status | Status | Processing status. |
| weight | Weight | User weight at scan time. |
| height | Height | User height at scan time. |
| measurements | Measurements? | Body measurements (when ready). |
| bodyfat | Bodyfat? | Body fat data (when ready). |
| scanAssets | ScanAsset? | Scan assets. |
| createdAt | Date | Creation timestamp. |
| updatedAt | Date | Update timestamp. |
NewScan
public struct NewScan: Codable, Sendable
| Property | Type | Description |
| deviceConfigName | String | Device configuration name. |
| userToken | String | User token. |
| bodyfatMethod | BodyfatMethod? | Body fat calculation method. |
| assetConfigId | AssetConfigId? | Asset configuration ID. |
UnitSystem
public enum UnitSystem: String, Codable
| Case | Description |
| .imperial | Inches, pounds. |
| .metric | Meters, kilograms. |
public struct Measurements: Codable, Sendable
All properties are Double values in the requested unit system.
| Property | Body Region |
| neckFit | Neck circumference |
| shoulderFit | Shoulder width |
| chestFit | Chest circumference |
| waistFit | Waist circumference |
| hipsFit | Hips circumference |
| thighLeftFit / thighRightFit | Mid-thigh |
| calfLeftFit / calfRightFit | Calf |
| midArmLeftFit / midArmRightFit | Bicep |
| forearmLeftFit / forearmRightFit | Forearm |
| wristLeftFit / wristRightFit | Wrist |
| waistToHipRatio | Waist-to-hip ratio |
public struct HealthReport: Codable, Identifiable
| Property | Type | Description |
| scan | ScanInfo | Scan metadata. |
| user | UserInfo | User information. |
| bodyFatPercentageReport | BodyFatPercentageReport | Body fat % with health label. |
| leanMassReport | LeanMassReport | Lean mass analysis. |
| fatMassReport | FatMassReport | Fat mass analysis. |
| waistCircumferenceReport | WaistCircumferenceReport | Waist health analysis. |
| waistToHipRatioReport | WaistToHipRatioReport | WHR analysis. |
| waistToHeightRatioReport | WaistToHeightRatioReport | WHtR analysis. |
| metabolismReport | MetabolismReport | BMR, TDEE, caloric recommendations. |
| metabolicAgeReport | MetabolicAgeReport? | Estimated metabolic age. |
User
public struct User: Codable, Sendable
| Property | Type | Description |
| id | String | Internal user ID. |
| token | String | Your unique identifier. |
| email | String? | User email. |
| sex | Sex | User sex. |
| region | String | User region. |
| birthDate | Date | Birth date. |
| weight | Weight | User weight. |
| height | Height | User height. |
| researchConsent | Bool | Research consent flag. |
NewUser
public struct NewUser: Codable, Sendable
All User fields plus termsOfService: TermsOfService.
ExistingUser
public struct ExistingUser: Codable, Sendable
Update payload. Only token is required; all other fields optional.
Sex
public enum Sex: String, Codable, CaseIterable
Cases: .male, .female, .neutral
Height
public struct Height: Codable, Sendable
| Property | Type | Description |
| value | Double | Height value. |
| unit | Height.Unit | .inches or .meters. |
Weight
public struct Weight: Codable, Sendable
| Property | Type | Description |
| value | Double | Weight value. |
| unit | Weight.Unit | .pounds or .kilograms. |
BodyfatMethod
public enum BodyfatMethod: String, Codable, CaseIterable
Cases: .adam, .army, .army_athlete, .coco, .coco2, .coco_legacy, .coco_bri, .extended_navy_thinboost, .tina_fit
PrismError
public struct PrismError: Codable, Sendable
| Property | Type | Description |
| statusCode | Int | HTTP status code. |
| messages | [String] | Error messages. |
| error | String? | Underlying error. |
Version
public struct Version
| Property | Type | Description |
| .current | Version | Current SDK version (static). |
| major / minor / patch | UInt | Version components. |
| build | UInt | Build number. |
| semanticVersionNumber | String | "X.Y.Z" format. |