# How to Integrate OpenMedKit Swift Library in iOS Apps: MLX and CoreML Setup

> Integrate OpenMedKit Swift library in iOS apps. Set up MLX or CoreML, then extract PII on-device for clinical entity extraction. Fast and efficient on-device processing.

- Repository: [Maziyar Panahi/openmed](https://github.com/maziyarpanahi/openmed)
- Tags: how-to-guide
- Published: 2026-06-11

---

**Add OpenMedKit via Swift Package Manager, initialize it with either the MLX backend for Apple Silicon devices or the CoreML backend for bundled models, then call `extractPII(_:)` to perform on-device clinical entity extraction.**

OpenMedKit is a Swift package from the maziyarpanahi/openmed repository that brings HIPAA-compliant clinical NLP—specifically named entity recognition (NER) and PII de-identification—directly to iOS, iPadOS, and macOS applications. To integrate OpenMedKit Swift library in iOS apps, you import the package, configure a backend, and invoke the high-level API on user text.

## Installation via Swift Package Manager

You can add the dependency using Xcode's GUI or by editing your [`Package.swift`](https://github.com/maziyarpanahi/openmed/blob/main/Package.swift) directly.

**Via Xcode**

1. Choose **File > Add Packages…**
2. Enter the repository URL: `https://github.com/maziyarpanahi/openmed`
3. Select the **OpenMedKit** product and add it to your app target

**Via Package.swift**

```swift
// swift-tools-version:5.9
import PackageDescription

let package = Package(
    name: "YourApp",
    dependencies: [
        .package(url: "https://github.com/maziyarpanahi/openmed.git", from: "1.5.5")
    ],
    targets: [
        .executableTarget(
            name: "YourApp",
            dependencies: [
                .product(name: "OpenMedKit", package: "openmed")
            ]
        )
    ]
)

```

The package manifest is defined in [`swift/OpenMedKit/Package.swift`](https://github.com/maziyarpanahi/openmed/blob/main/swift/OpenMedKit/Package.swift) and includes dependencies for MLX, Transformers, and ZIPFoundation.

## Choosing Your Inference Backend

OpenMedKit abstracts the model runtime behind the `OpenMedBackend` enum defined in [`OpenMedBackend.swift`](https://github.com/maziyarpanahi/openmed/blob/main/OpenMedBackend.swift). You must choose between two execution paths:

- **MLX**: Downloads Apple Silicon-optimized models from Hugging Face and runs inference locally using the MLX framework. Best for production iPhones and iPads.
- **CoreML**: Loads a pre-converted `.mlmodelc` bundle shipped with your app. Required for iOS simulator testing or when you have existing CoreML assets.

### MLX Backend Setup (Recommended for Devices)

The MLX backend requires downloading the model artifact on first launch. Use `OpenMedModelStore.downloadMLXModel(repoID:)` defined in [`OpenMedModelStore.swift`](https://github.com/maziyarpanahi/openmed/blob/main/OpenMedModelStore.swift) to handle caching and file management.

```swift
import OpenMedKit

// Download and cache the model (async, runs once)
let modelDirectory = try await OpenMedModelStore.downloadMLXModel(
    repoID: "OpenMed/OpenMed-PII-ClinicalE5-Small-33M-v1-mlx"
)

// Initialize with MLX backend
let openmed = try OpenMed(
    backend: .mlx(modelDirectoryURL: modelDirectory)
)

// Extract PII entities
let entities = try openmed.extractPII(
    "Patient John Doe, DOB 1990-05-15, SSN 123-45-6789"
)

// entities is [EntityPrediction] containing label, text, confidence, and spans

```

### CoreML Backend Setup (For Simulator or Bundled Models)

Use the CoreML backend when testing on simulators or when you prefer to bundle a converted model with your app binary. You need both the `.mlmodelc` directory and an [`id2label.json`](https://github.com/maziyarpanahi/openmed/blob/main/id2label.json) mapping file.

```swift
import OpenMedKit

// Locate bundled resources
let modelURL = Bundle.main.url(
    forResource: "OpenMedPII", 
    withExtension: "mlmodelc"
)!
let labelURL = Bundle.main.url(
    forResource: "id2label", 
    withExtension: "json"
)!

// Initialize with CoreML backend
let openmed = try OpenMed(
    backend: .coreML(
        modelURL: modelURL,
        id2labelURL: labelURL,
        tokenizerName: "OpenMed/OpenMed-PII-ClinicalE5-Small-33M-v1"
    )
)

// Run inference
let entities = try openmed.extractPII("Patient Jane Doe, MRN 123456")

```

The convenience initializer for the CoreML backend resides in [`OpenMedKit.swift`](https://github.com/maziyarpanahi/openmed/blob/main/OpenMedKit.swift).

## Implementing Clinical NLP in SwiftUI

The following example mirrors the implementation in [`swift/OpenMedScanDemo/OpenMedScanDemo/ContentView.swift`](https://github.com/maziyarpanahi/openmed/blob/main/swift/OpenMedScanDemo/OpenMedScanDemo/ContentView.swift), demonstrating async model loading and entity display.

```swift
import SwiftUI
import OpenMedKit

struct ClinicalDocumentView: View {
    @State private var text = "Patient: Jane Doe, DOB: 01/15/1970, SSN: 000-00-0000"
    @State private var entities: [EntityPrediction] = []
    @State private var isLoading = false
    @State private var errorMessage: String?

    var body: some View {
        VStack(spacing: 16) {
            TextEditor(text: $text)
                .frame(height: 120)
                .border(Color.gray.opacity(0.5))

            Button(action: detectPII) {
                if isLoading {
                    ProgressView()
                } else {
                    Text("Detect PII")
                }
            }
            .disabled(isLoading)

            if let error = errorMessage {
                Text(error).foregroundColor(.red)
            }

            List(entities) { entity in
                VStack(alignment: .leading) {
                    Text("[\(entity.label)] \(entity.text)")
                        .font(.headline)
                    Text("Confidence: \(entity.confidence, specifier: "%.3f")")
                        .font(.caption)
                        .foregroundColor(.secondary)
                }
            }
        }
        .padding()
    }

    private func detectPII() {
        isLoading = true
        errorMessage = nil

        Task {
            do {
                // Switch to .coreML if running on simulator
                let modelDir = try await OpenMedModelStore.downloadMLXModel(
                    repoID: "OpenMed/OpenMed-PII-ClinicalE5-Small-33M-v1-mlx"
                )
                let openmed = try OpenMed(backend: .mlx(modelDirectoryURL: modelDir))
                entities = try openmed.extractPII(text)
            } catch {
                errorMessage = error.localizedDescription
            }
            isLoading = false
        }
    }
}

```

## Key Source Files and Architecture

Understanding these files helps when debugging or extending functionality:

- **[`swift/OpenMedKit/Package.swift`](https://github.com/maziyarpanahi/openmed/blob/main/swift/OpenMedKit/Package.swift)**: Defines the Swift package structure and external dependencies (MLX, Transformers).
- **[`OpenMedBackend.swift`](https://github.com/maziyarpanahi/openmed/blob/main/OpenMedBackend.swift)**: Contains the `OpenMedBackend` enum with `.mlx(modelDirectoryURL:)` and `.coreML(modelURL:id2labelURL:tokenizerName:)` cases.
- **[`OpenMedModelStore.swift`](https://github.com/maziyarpanahi/openmed/blob/main/OpenMedModelStore.swift)**: Implements `downloadMLXModel(repoID:)` for Hugging Face artifact management and local caching.
- **[`OpenMedKit.swift`](https://github.com/maziyarpanahi/openmed/blob/main/OpenMedKit.swift)**: Houses the `OpenMed` class public API, including `extractPII(_:confidenceThreshold:)` and `analyzeText(_:confidenceThreshold:)`.
- **[`PostProcessing.swift`](https://github.com/maziyarpanahi/openmed/blob/main/PostProcessing.swift)**: Smart post-processing logic for entity span repair and merging.
- **[`ContentView.swift`](https://github.com/maziyarpanahi/openmed/blob/main/ContentView.swift)**: Reference SwiftUI implementation in the demo app showing end-to-end integration.

## Summary

- **Add dependency**: Use Swift Package Manager with `https://github.com/maziyarpanahi/openmed`
- **Choose backend**: **MLX** for Apple Silicon performance on real devices; **CoreML** for simulator or bundled models
- **Download MLX models**: Call `OpenMedModelStore.downloadMLXModel(repoID:)` to cache Hugging Face artifacts locally
- **Bundle CoreML models**: Include `.mlmodelc` directories and [`id2label.json`](https://github.com/maziyarpanahi/openmed/blob/main/id2label.json) files in your app target
- **Initialize**: Create an `OpenMed` instance using `OpenMed(backend: .mlx(...))` or `OpenMed(backend: .coreML(...))`
- **Extract entities**: Invoke `extractPII(_:confidenceThreshold:)` to receive `[EntityPrediction]` results with labels, confidence scores, and character spans

## Frequently Asked Questions

### Can I use OpenMedKit on the iOS simulator?

Yes, but only with the **CoreML** backend. The MLX backend requires Apple Silicon hardware and will not run on Intel-based simulators. For simulator testing, bundle a converted CoreML model (`.mlmodelc`) and initialize with `OpenMed(backend: .coreML(modelURL:id2labelURL:tokenizerName:))`.

### What is the difference between `extractPII` and `analyzeText`?

Both methods perform named entity recognition defined in [`OpenMedKit.swift`](https://github.com/maziyarpanahi/openmed/blob/main/OpenMedKit.swift). **`extractPII(_:confidenceThreshold:)`** specifically targets personally identifiable information in clinical text (names, dates, SSNs, medical record numbers), while **`analyzeText(_:confidenceThreshold:)`** provides general clinical entity analysis. Both return arrays of `EntityPrediction` objects containing the entity text, label, confidence score, and character positions.

### How does OpenMedKit handle model caching?

The `OpenMedModelStore.downloadMLXModel(repoID:)` method in [`OpenMedModelStore.swift`](https://github.com/maziyarpanahi/openmed/blob/main/OpenMedModelStore.swift) automatically caches downloaded MLX artifacts in the application's local filesystem. Subsequent calls return the cached path immediately, avoiding redundant network requests across app launches.

### Which backend offers better performance on modern iPhones?

The **MLX** backend delivers superior performance on iPhone 12, iPad Air/Pro, and Apple Silicon Macs by leveraging the Neural Engine and GPU acceleration. CoreML provides broader compatibility, particularly for older devices or when you require simulator support, but may have higher latency for complex clinical documents.