iOS / macOS
Native Swift SDK for on-device ML inference
The Swift SDK provides native bindings to the Xybrid runtime via UniFFI for iOS and macOS applications.
The Swift SDK is in early access. Releases ship a prebuilt XybridFFI xcframework via Swift Package Manager. Known issue: building for the iOS Simulator on Apple Silicon requires the useLocalNatives = true workaround — see #179. For cross-platform development, see the Flutter SDK.
Installation
Add the Xybrid package via Swift Package Manager:
dependencies: [
.package(url: "https://github.com/xybrid-ai/xybrid", from: "0.2.2")
]Or in Xcode: File > Add Package Dependencies and enter the repository URL.
Supported platforms: iOS 13.0+, macOS 10.15+
Quick Start
import Xybrid
@main
struct MyApp: App {
init() { Xybrid.initialize() }
var body: some Scene { /* ... */ }
}
// Load a model from the registry
let loader = ModelLoader.fromRegistry(modelId: "kokoro-82m")
let model = try loader.load()
// Run inference
let envelope = Envelope.text("Hello, world!")
let result = try model.run(envelope: envelope)
if result.success {
print("Output: \(result.text ?? "")")
print("Latency: \(result.latency)s")
}On iOS, Xybrid.initialize() enables UIDevice battery monitoring and subscribes to UIDevice.batteryLevelDidChangeNotification, forwarding readings to the routing engine. Thermal state on Apple platforms is sourced from NSProcessInfo.thermalState directly in xybrid-core.
Initialization
Inference runs entirely on-device whether or not you authenticate. Pass an apiKey to light up the dashboard — that single call starts the telemetry exporter, and your model.run(...) calls automatically emit execution traces:
Xybrid.initialize(
apiKey: ProcessInfo.processInfo.environment["XYBRID_API_KEY"]
)Without a key, telemetry is disabled and the first inference logs a one-shot hint pointing at the dashboard (suppress with the XYBRID_QUIET=1 environment variable). Get a free key at dashboard.xybrid.dev. For a self-hosted dashboard, also pass ingestUrl.
Model Loading
From Registry
let loader = ModelLoader.fromRegistry(modelId: "whisper-tiny")
let model = try loader.load()From Local Bundle
let loader = ModelLoader.fromBundle(path: bundlePath)
let model = try loader.load()Input Envelopes
Audio (Speech Recognition)
let envelope = Envelope.audio(pcmData: audioData, sampleRate: 16000, channels: 1)
let result = try model.run(envelope: envelope)
print("Transcription: \(result.text ?? "")")Text (Text-to-Speech)
// Simple text
let envelope = Envelope.text("Hello, how are you?")
// With voice and speed
let envelope = Envelope.text("Hello", voice: "af_heart", speed: 1.0)
let result = try model.run(envelope: envelope)
if let audioBytes = result.audioBytes {
// Play or save audio
}Embedding
let envelope = Envelope.embedding(data: [0.1, 0.2, 0.3])
let result = try model.run(envelope: envelope)
if let vector = result.embedding {
// Process embedding vector
}Result Handling
let result = try model.run(envelope: envelope)
if result.success {
switch result.outputType {
case "text":
print("Text: \(result.text!)")
case "audio":
playAudio(result.audioBytes!)
case "embedding":
process(result.embedding!)
default:
break
}
print("Latency: \(result.latency)s") // TimeInterval in seconds
} else {
print("Error: \(result.error ?? "Unknown")")
}XybridResult Properties
| Property | Type | Description |
|---|---|---|
success | Bool | Whether inference succeeded |
error | String? | Error message if failed |
outputType | String | "text", "audio", or "embedding" |
text | String? | Text output (ASR, LLM) |
audioBytes | Data? | Audio output (TTS) |
embedding | [Float]? | Embedding vector |
latencyMs | UInt32 | Inference latency in ms |
isFailure | Bool | Convenience: !success |
latency | TimeInterval | Latency in seconds |
Error Handling
The SDK uses a Swift error enum for type-safe error handling:
do {
let model = try ModelLoader.fromRegistry(modelId: "kokoro-82m").load()
let result = try model.run(envelope: envelope)
} catch XybridError.ModelNotFound(let modelId) {
print("Model not found: \(modelId)")
} catch XybridError.InferenceFailed(let message) {
print("Inference failed: \(message)")
} catch XybridError.InvalidInput(let message) {
print("Invalid input: \(message)")
} catch XybridError.IoError(let message) {
print("I/O error: \(message)")
} catch {
print("Unexpected error: \(error.localizedDescription)")
}Type Aliases
The SDK provides short aliases for convenience:
| Alias | Full Type |
|---|---|
ModelLoader | XybridModelLoader |
Model | XybridModel |
Envelope | XybridEnvelope |
Result | XybridResult |
Platform Support
| Platform | Status | Accelerators |
|---|---|---|
| iOS | Supported | Metal, CoreML, ANE |
| macOS (Apple Silicon) | Supported | Metal, CoreML, ANE |
| macOS (Intel) | Supported | CPU |