iOS On-Device AI Models
Production-ready guide for implementing on-device AI models in iOS apps using Apple's Foundation Models framework and MLX Swift.
When to Use This Skill
- Implementing local LLM inference in iOS apps
- Building chat interfaces with Foundation Models
- Integrating Vision Language Models (VLMs)
- Adding text embeddings or image generation
- Implementing tool/function calling with LLMs
- Managing multi-turn conversations
- Optimizing memory usage for on-device models
- Supporting internationalization in AI features
Core Principles
- Compatibility Gate - Foundation Models requires iOS 26, iPadOS 26, or macOS 26 or later, and an Apple Intelligence-capable device with Apple Intelligence enabled. Compare this floor with the deployment target and with every device the feature must support before you select a framework. Always check
SystemLanguageModel.default.availability at runtime before you create a session. Show a fallback UI for each unavailable state: .modelNotReady (model not ready, for example a download in progress), .appleIntelligenceNotEnabled (disabled in Settings), and .deviceNotEligible (hardware cannot run the model). A runtime check reports the state of one device. It cannot make the feature available on an OS version or device below the floor.
- Single-Flight Streaming - Give one isolation boundary ownership of each conversation's session, transcript, and generation task. Do not call the session while
isResponding is true; reject or queue the new send so that GenerationError.concurrentRequests never occurs in normal use. Stop and teardown cancel the owned task and await it before a new send starts. Check Task.checkCancellation() while you consume the stream. Commit a transcript turn only when the response completes.
- Session Persistence - Reuse LanguageModelSession across completed turns and keep partial streaming text separate from committed history.
- Memory Awareness - Use quantized models and monitor memory usage. iOS limits one app to a fraction of the device's total RAM. Reject any model whose weight files are about the size of, or larger than, the total RAM of the lowest-memory required device: it cannot load. Pick the smallest model that meets quality on that device and measure peak memory there. Give one
@Observable owner the load state, the loaded model, and generation. For a multi-gigabyte download, ask for consent, default to Wi-Fi, make the download resumable, and keep the feature in an explicit "not downloaded" state until the files are complete.
- Async Everything - Load models asynchronously, never block the main thread.
- Device Proof - Before calling the design viable, exercise support boundaries and generation lifecycle in focused tests, then verify a Release build on the oldest or lowest-memory required physical device, including offline operation when the product promises on-device behavior.
- Locale Support - Call
supportsLocale(_:) for each user locale before you create a session. Treat an unsupported locale as an unavailable state; do not use a prompt instruction such as "answer in " to work around it. For a supported locale, put the locale in the session instructions, not in each prompt. Test each locale branch on a physical device set to that locale.
- Typed Tools and Outputs - For structured output, define a
@Generable type and call respond(to:generating:); do not parse free text with regular expressions. For an app action the model needs, implement the Foundation Models Tool protocol with @Generable arguments and pass the tool when you create the session. The session invokes the tool. The view never calls the service on the model's behalf. A tool error surfaces from the session call as LanguageModelSession.ToolCallError. Catch it and show the user a normal failure state; never crash or show an empty result.
Quick Reference
Framework Comparison
| Topic |
Guide |
| Framework comparison and selection |
framework-selection.md |
Foundation Models (Apple's Framework)
| Topic |
Guide |
| Setup and configuration |
foundation-models/setup.md |
| Chat patterns and conversations |
foundation-models/chat-patterns.md |
MLX Swift (Advanced Features)
| Topic |
Guide |
| Setup and configuration |
mlx-swift/setup.md |
| Chat patterns with custom models |
mlx-swift/chat-patterns.md |
| Vision Language Models (VLMs) |
mlx-swift/vision-patterns.md |
| Tool calling, embeddings, structured gen |
mlx-swift/advanced-patterns.md |
| Model quantization with MLX-LM |
mlx-swift/quantization.md |
Shared (Both Frameworks)
| Topic |
Guide |
| Best practices and optimization |
shared/best-practices.md |
| Error handling and recovery |
shared/error-handling.md |
| Testing strategies |
shared/testing.md |
Quick Decision Trees
Which framework should I use?
Is Foundation Models available on every OS version and device the feature
must support (iOS 26 or later, Apple Intelligence-capable hardware)?
├── No → Can a suitable MLX model meet the same device floor?
│ ├── Yes → MLX Swift (prove memory, latency, and output on that floor)
│ └── No → The requirements are infeasible; change the support contract
└── Yes → Do you need VLMs, image generation, or custom models?
├── Yes → MLX Swift (references/mlx-swift/)
└── No → Foundation Models (references/foundation-models/)
Where should I start?
New to on-device AI?
└── Start with Foundation Models:
1. Read framework-selection.md
2. Follow foundation-models/setup.md
3. Implement foundation-models/chat-patterns.md
Need advanced features?
└── Use MLX Swift:
1. Read framework-selection.md
2. Follow mlx-swift/setup.md
3. Choose pattern:
- Chat: mlx-swift/chat-patterns.md
- Vision: mlx-swift/vision-patterns.md
- Advanced: mlx-swift/advanced-patterns.md
Where should my model loading code live?
Is this model shared across features?
├── Yes → Create @Observable service in app/services/
└── No → Is it feature-specific?
├── Yes → Create @Observable class in feature/
└── No → Load inline with @State (simple cases only)
How should I handle conversations?
Foundation Models:
└── Reuse LanguageModelSession for context
(references/foundation-models/chat-patterns.md #multi-turn)
MLX Swift:
└── Implement custom context management
(references/mlx-swift/chat-patterns.md)
What generation parameters should I use?
What's the use case?
Factual answers (summaries, facts)
└── temperature: 0.1-0.3
Balanced (chat, Q&A)
└── temperature: 0.6-0.8
Creative (storytelling, ideas)
└── temperature: 0.9-1.2
See references/shared/best-practices.md for details
Resources
1---2name: local-ai-models3description: WHEN building iOS features on on-device models with Foundation Models or MLX Swift: local LLM inference, chat, Vision Language Models (VLMs), text embeddings, image generation, tool calling, multi-turn conversations, custom models, or structured generation; NOT for cloud-hosted model APIs, Core ML or coremltools model conversion, or Vision framework classifiers; returns framework selection, compatibility gates, session and streaming patterns, and device-proof verification plans.4---56# iOS On-Device AI Models78Production-ready guide for implementing on-device AI models in iOS apps using Apple's Foundation Models framework and MLX Swift.910## When to Use This Skill1112- Implementing local LLM inference in iOS apps13- Building chat interfaces with Foundation Models14- Integrating Vision Language Models (VLMs)15- Adding text embeddings or image generation16- Implementing tool/function calling with LLMs17- Managing multi-turn conversations18- Optimizing memory usage for on-device models19- Supporting internationalization in AI features2021## Core Principles22231. **Compatibility Gate** - Foundation Models requires iOS 26, iPadOS 26, or macOS 26 or later, and an Apple Intelligence-capable device with Apple Intelligence enabled. Compare this floor with the deployment target and with every device the feature must support before you select a framework. Always check `SystemLanguageModel.default.availability` at runtime before you create a session. Show a fallback UI for each unavailable state: `.modelNotReady` (model not ready, for example a download in progress), `.appleIntelligenceNotEnabled` (disabled in Settings), and `.deviceNotEligible` (hardware cannot run the model). A runtime check reports the state of one device. It cannot make the feature available on an OS version or device below the floor.242. **Single-Flight Streaming** - Give one isolation boundary ownership of each conversation's session, transcript, and generation task. Do not call the session while `isResponding` is true; reject or queue the new send so that `GenerationError.concurrentRequests` never occurs in normal use. Stop and teardown cancel the owned task and await it before a new send starts. Check `Task.checkCancellation()` while you consume the stream. Commit a transcript turn only when the response completes.253. **Session Persistence** - Reuse LanguageModelSession across completed turns and keep partial streaming text separate from committed history.264. **Memory Awareness** - Use quantized models and monitor memory usage. iOS limits one app to a fraction of the device's total RAM. Reject any model whose weight files are about the size of, or larger than, the total RAM of the lowest-memory required device: it cannot load. Pick the smallest model that meets quality on that device and measure peak memory there. Give one `@Observable` owner the load state, the loaded model, and generation. For a multi-gigabyte download, ask for consent, default to Wi-Fi, make the download resumable, and keep the feature in an explicit "not downloaded" state until the files are complete.275. **Async Everything** - Load models asynchronously, never block the main thread.286. **Device Proof** - Before calling the design viable, exercise support boundaries and generation lifecycle in focused tests, then verify a Release build on the oldest or lowest-memory required physical device, including offline operation when the product promises on-device behavior.297. **Locale Support** - Call `supportsLocale(_:)` for each user locale before you create a session. Treat an unsupported locale as an unavailable state; do not use a prompt instruction such as "answer in <language>" to work around it. For a supported locale, put the locale in the session instructions, not in each prompt. Test each locale branch on a physical device set to that locale.308. **Typed Tools and Outputs** - For structured output, define a `@Generable` type and call `respond(to:generating:)`; do not parse free text with regular expressions. For an app action the model needs, implement the Foundation Models `Tool` protocol with `@Generable` arguments and pass the tool when you create the session. The session invokes the tool. The view never calls the service on the model's behalf. A tool error surfaces from the session call as `LanguageModelSession.ToolCallError`. Catch it and show the user a normal failure state; never crash or show an empty result.3132## Quick Reference3334### Framework Comparison3536| Topic | Guide |37| ---------------------------------- | ----------------------------------------------------------- |38| Framework comparison and selection | [framework-selection.md](references/framework-selection.md) |3940### Foundation Models (Apple's Framework)4142| Topic | Guide |43| ------------------------------- | ----------------------------------------------------------------------------------- |44| Setup and configuration | [foundation-models/setup.md](references/foundation-models/setup.md) |45| Chat patterns and conversations | [foundation-models/chat-patterns.md](references/foundation-models/chat-patterns.md) |4647### MLX Swift (Advanced Features)4849| Topic | Guide |50| ---------------------------------------- | --------------------------------------------------------------------------- |51| Setup and configuration | [mlx-swift/setup.md](references/mlx-swift/setup.md) |52| Chat patterns with custom models | [mlx-swift/chat-patterns.md](references/mlx-swift/chat-patterns.md) |53| Vision Language Models (VLMs) | [mlx-swift/vision-patterns.md](references/mlx-swift/vision-patterns.md) |54| Tool calling, embeddings, structured gen | [mlx-swift/advanced-patterns.md](references/mlx-swift/advanced-patterns.md) |55| Model quantization with MLX-LM | [mlx-swift/quantization.md](references/mlx-swift/quantization.md) |5657### Shared (Both Frameworks)5859| Topic | Guide |60| ------------------------------- | --------------------------------------------------------------- |61| Best practices and optimization | [shared/best-practices.md](references/shared/best-practices.md) |62| Error handling and recovery | [shared/error-handling.md](references/shared/error-handling.md) |63| Testing strategies | [shared/testing.md](references/shared/testing.md) |6465## Quick Decision Trees6667### Which framework should I use?6869```70Is Foundation Models available on every OS version and device the feature71must support (iOS 26 or later, Apple Intelligence-capable hardware)?72├── No → Can a suitable MLX model meet the same device floor?73│ ├── Yes → MLX Swift (prove memory, latency, and output on that floor)74│ └── No → The requirements are infeasible; change the support contract75└── Yes → Do you need VLMs, image generation, or custom models?76 ├── Yes → MLX Swift (references/mlx-swift/)77 └── No → Foundation Models (references/foundation-models/)78```7980### Where should I start?8182```83New to on-device AI?84└── Start with Foundation Models:85 1. Read framework-selection.md86 2. Follow foundation-models/setup.md87 3. Implement foundation-models/chat-patterns.md8889Need advanced features?90└── Use MLX Swift:91 1. Read framework-selection.md92 2. Follow mlx-swift/setup.md93 3. Choose pattern:94 - Chat: mlx-swift/chat-patterns.md95 - Vision: mlx-swift/vision-patterns.md96 - Advanced: mlx-swift/advanced-patterns.md97```9899### Where should my model loading code live?100101```102Is this model shared across features?103├── Yes → Create @Observable service in app/services/104└── No → Is it feature-specific?105 ├── Yes → Create @Observable class in feature/106 └── No → Load inline with @State (simple cases only)107```108109### How should I handle conversations?110111```112Foundation Models:113└── Reuse LanguageModelSession for context114 (references/foundation-models/chat-patterns.md #multi-turn)115116MLX Swift:117└── Implement custom context management118 (references/mlx-swift/chat-patterns.md)119```120121### What generation parameters should I use?122123```124What's the use case?125126Factual answers (summaries, facts)127└── temperature: 0.1-0.3128129Balanced (chat, Q&A)130└── temperature: 0.6-0.8131132Creative (storytelling, ideas)133└── temperature: 0.9-1.2134135See references/shared/best-practices.md for details136```137138## Resources139140- [MLX Swift Examples](https://github.com/ml-explore/mlx-swift-examples)141- [Foundation Models Docs](https://developer.apple.com/documentation/foundationmodels)142- [Hugging Face Model Hub](https://huggingface.co/models)143- [MLX-LM Quantization](https://github.com/ml-explore/mlx-examples/tree/main/llms)144- [MLX Community Models](https://huggingface.co/mlx-community)