SystemLanguageModel Availability: Gating On-Device AI for Every Apple Device
- Author
- Ehsan Azish · 3NSOFTS
- Updated
- June 2026
- Read time
- 12 min read
- Level
- Intermediate
- Platform
- iOS 26+, Foundation Models, SwiftUI
Implementation Notes
- ~/ What broke: The AI feature assumed the system language model was always ready.
- ~/ What to do: Gate features on SystemLanguageModel availability before showing AI entry points.
The single most common mistake shipping Foundation Models: assuming the model is there. It frequently isn't. A large share of your install base runs devices that cannot run the on-device model — older silicon, AI features disabled, model still downloading, or unsupported region/locale. If your feature assumes availability, it breaks silently for those users.
The fix is to gate every AI feature behind SystemLanguageModel.availability and design a real fallback for the unavailable case. This guide covers the availability matrix and the UI patterns that handle it cleanly.
The availability API
SystemLanguageModel.default.availability returns an enum describing whether the model can run right now on this device — and if not, why.
import FoundationModels
let model = SystemLanguageModel.default
switch model.availability {
case .available:
// Safe to create sessions and generate.
break
case .unavailable(let reason):
// Do NOT create sessions. Route to fallback.
handleUnavailable(reason)
@unknown default:
handleUnavailable(nil)
}
The reason distinguishes cases you should treat differently:
- Device not eligible — the hardware can't run the model. Permanent for this device. Hide the feature; don't tease something the user can never get.
- Apple Intelligence not enabled — eligible device, feature toggled off. Recoverable by the user. Offer guidance to enable it.
- Model not ready — eligible, enabled, but assets still downloading. Transient. Show a "setting up" state and re-check.
Treating all three as one "unavailable" bucket produces bad UX: you'll either nag eligible users to enable a feature they already have, or prompt ineligible users to enable something their hardware doesn't support.
The device matrix you're actually targeting
Foundation Models requires recent Apple silicon — A17 Pro / M-series class and newer — plus Apple Intelligence enabled and the region supported. In practice this means:
- A meaningful fraction of active iPhones cannot run it at all.
- Eligible devices may still be mid-download on first launch after an OS update.
- Region and language settings can render an otherwise-capable device unavailable.
Design for the assumption that availability is the exception you must earn, not the default you can assume. Your feature's baseline experience should not require the model.
SwiftUI gating pattern
Drive UI off availability so the AI affordance only appears when it can actually function:
struct SmartSummaryView: View {
private let model = SystemLanguageModel.default
let document: Document
var body: some View {
switch model.availability {
case .available:
AISummaryView(document: document) // the enhanced path
case .unavailable(let reason):
switch reason {
case .appleIntelligenceNotEnabled:
EnableIntelligencePrompt() // actionable nudge
case .modelNotReady:
ModelSettingUpView() // transient, re-check
default:
ManualSummaryView(document: document) // hardware ineligible: just work
}
@unknown default:
ManualSummaryView(document: document)
}
}
}
Confirm the exact
reasoncase names against your SDK version — Apple has refined this enum across point releases. Keep the mapping in one switch so it's a one-line edit when names change, and always include@unknown default.
Re-check availability when the app returns to the foreground (scenePhase), because a model that was downloading on launch may be ready by the time the user comes back.
Don't tease ineligible hardware
A subtle product mistake: showing an "AI Summary ✨" button to a user whose device can never run it, then having it fail or show an upsell. That's a broken promise. For hardware-ineligible devices, the AI affordance should not exist — present the deterministic feature as the whole feature, with no missing-AI framing.
This is also why your fallback must be genuinely good, not a degraded stub. For a summarizer, the fallback might be a sensible extractive summary. For tagging, a keyword heuristic. The non-AI path is the experience for a real chunk of your users — treat it as a first-class feature.
Availability vs. runtime errors
Availability gating and GenerationError handling are complementary, not redundant:
- Availability answers "should I even offer this feature on this device?" — checked before creating a session.
GenerationErroranswers "this specific generation failed" — handled after arespond(to:)on an available model.
You need both. Availability prevents you from creating sessions that can't work; error handling catches the failures that happen on sessions that should work. (See the GenerationError reference.)
Production checklist
- Check
availabilitybefore creating any session — never assume. - Distinguish the three unavailable reasons — ineligible / not-enabled / not-ready get different UI.
- Hide AI affordances on ineligible hardware — don't tease an impossible feature.
- Re-check on foreground — downloading models become ready.
- Make the non-AI fallback first-class — it's the real experience for many users.
- Include
@unknown defaulton every availability and reason switch.
Why this matters for shipped apps
On-device AI is marketed as "it just runs locally," which hides that it only runs locally on some devices, sometimes. An app architected around guaranteed availability looks great in the simulator and on your A17 Pro test phone, then quietly fails for a third of your users. Gating availability correctly — and building a fallback you'd ship even without AI — is what makes the feature dependable across the whole install base.
Designing an on-device AI feature that has to work across the full Apple device range? That degradation architecture is central to our on-device AI integration practice at 3NSOFTS.