Super-simple API for Apple Foundation Models in Swift (iOS 26+, macOS 26+).
A lightweight façade designed for beginners: generate text or strongly-typed results in one line.
- ✅ Plain text generation — pass a prompt, get back a string.
- ✅ Guided typed generation — decode directly into your own
Decodable & Generablestructs. - ✅ Streaming Text Generation — get incremental text chunks as they’re produced
- ✅ Beginner-friendly API — minimal surface, sensible defaults.
- ✅ On-device — powered by Apple’s Foundation Models framework, no server required.
- ✅ Future-proof — extend with streaming, tools, and advanced options later.
SwiftFM requires the Apple Intelligence Foundation Models, which are only available on:
- iOS 26 or later
- iPadOS 26 or later
- macOS 26 or later
SwiftFM is fully Swift 6 ready.
- All types conform to
Sendablewhere appropriate. - Concurrency is handled safely with actor isolation.
- Package settings enable Strict Concurrency checking for maximum safety.
Add SwiftFM to your project using Swift Package Manager:
- In Xcode: File → Add Packages…
- Enter the repository URL: https://github.com/ricky-stone/SwiftFM
- Select main branch or a tagged version (e.g.
0.1.0).
import SwiftFM
let fm = SwiftFM()
Task {
do {
let response = try await fm.generateText(
for: "Explain a century break in snooker in one sentence."
)
print(response)
// "A century break is when a player scores 100 points or more in a single visit."
} catch {
print("Error:", error)
}
}To use guided generation, your type must conform to Decodable & Sendable & Generable.
@Generable
struct MatchPrediction: Decodable, Sendable {
@Guide(description: "First player’s name")
let player: String
@Guide(description: "Opponent’s name")
let opponent: String
@Guide(description: "Who is predicted to win")
let predictedWinner: String
@Guide(description: "Confidence 0.0–1.0")
let confidence: Double
}
let fm = SwiftFM()
Task {
do {
let prediction: MatchPrediction = try await fm.generateJSON(
for: """
Imagine a snooker match.
Choose two well-known players and predict the winner.
Return {player, opponent, predictedWinner, confidence}.
""",
as: MatchPrediction.self
)
print("Upcoming match: \(prediction.player) vs \(prediction.opponent)")
print("Predicted winner: \(prediction.predictedWinner) (\(Int(prediction.confidence * 100))%)")
} catch {
print("Error:", error)
}
}import SwiftFM
// Configure SwiftFM with a system role
let fm = SwiftFM(config: .init(system: "You are a professional snooker coach."))
Task {
do {
let tip = try await fm.generateText(
for: "Give me a practice drill to improve cue ball control."
)
print(tip)
// e.g. "Set up three reds in a line and practice stopping the cue ball dead after each pot."
} catch {
print("Error:", error)
}
}let fm = SwiftFM()
Task {
do {
for try await chunk in await fm.streamText(for: "Explain the rules of snooker step by step.") {
print(chunk, terminator: "")
}
} catch {
print("Stream failed:", error)
}
}SwiftUI Example
@State private var text = ""
Task {
do {
for try await chunk in await fm.streamText(for: "Explain the rules of snooker step by step.") {
text = chunk
}
} catch {
print("Stream failed:", error)
}
}if SwiftFM.isModelAvailable {
print("Foundation Model ready to use.")
} else {
print("Not available:", SwiftFM.modelAvailability)
}SwiftFM includes Swift Testing style tests to ensure everything works as expected on devices where Foundation Models are available.
SwiftFM is released under the MIT License.
This means: • You are free to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of this software. • The only requirements are that you include the original license and copyright notice in copies or substantial portions of the software. • The software is provided “as is”, without warranty of any kind.
SwiftFM was created by Ricky Stone.
If you use or modify this library, please consider including a reference such as:
“Based on Ricky Stone’s SwiftFM.”
This is not a requirement of the MIT License, but an appreciated courtesy.