当 Apple Intelligence 不可用时,如何优雅地回退
Source: Dev.to
介绍
Apple Intelligence 是近年来 iOS 开发者最令人振奋的进展之一。Foundation Models 框架让你能够直接在设备上访问大型语言模型——无需 API 费用、无需网络请求,并且完全保护隐私。
但残酷的现实是,相当大比例的用户无法运行它。如果你在应用中直接使用 LanguageModelSession() 而不做任何检查,就会向大量设备交付破碎的体验。
下面是一份简洁、可直接复制的指南,展示:
- 哪些设备无法使用 Apple Intelligence
- 框架报告的三种可用性状态
- 如何在 UI 中处理每种情况
- 一个简单、可复用的架构,帮助你保持功能代码整洁
谁不能使用 Apple Intelligence?
| iOS 版本 | 最低硬件 | Apple Intelligence 要求 |
|---|---|---|
| iOS 26.3 (Feb 11 2026) | iPhone 11 + (A13 或更新) | A17 Pro 或更新 |
只有以下设备符合硬件要求:
- iPhone 15 Pro / iPhone 15 Pro Max
- iPhone 16 / 16 Plus / 16 Pro / 16 Pro Max
- iPhone 16e
- iPhone 17 / 17 Pro / 17 Pro Max / iPhone Air
所有其他设备——包括标准的 iPhone 15——虽然运行 iOS 26.3,但 无法获得任何 Foundation Models 访问权限。
即使在符合条件的硬件上,你仍然需要:
- 在设置中 启用 Apple Intelligence(需自行选择)
- ≥ 7 GB 可用存储空间
- 设备和 Siri 语言设置为 受支持的语言
- 模型 已完整下载(启用后会在后台下载)
结论: 仅凭操作系统版本较新,不能假设模型可用。
三种不可用情况
SystemLanguageModel.default.availability 可以是三种 不可用 情况之一(以及正常的 .available 路径):
import FoundationModels
switch SystemLanguageModel.default.availability {
case .available:
// Good to go
case .unavailable(.deviceNotEligible):
// A13 or older chip – Foundation Models will never work here
case .unavailable(.appleIntelligenceNotEnabled):
// Compatible device, but user hasn't turned on Apple Intelligence
case .unavailable(.modelNotReady):
// Compatible + enabled, but model is still downloading
@unknown default:
// Future‑proof: handle any new cases Apple might add
break
}
每种情况都需要不同的用户体验响应。
构建合适的回退策略
将这三种情况视为三个独立的 UX 问题。
情况 1 – 设备不符合资格
永久 限制。硬件永远不支持 Apple Intelligence。
不要 显示加载指示或“稍后再试”之类的提示。相反,提供功能完整的非 AI 版本。
case .unavailable(.deviceNotEligible):
// Serve a non‑AI version of the feature
showBasicTextSummarizer()
示例: 在智能日记应用中,你可以跳过自动标签,让用户手动标记。 在写作助手中,你可以提供预设模板,而不是生成的建议。
情况 2 – Apple Intelligence 未启用
硬件具备能力,但用户尚未同意。你 可以 提示他们,但要温和:
case .unavailable(.appleIntelligenceNotEnabled):
showEnablementBanner(
message: "Enable Apple Intelligence in Settings to unlock AI‑powered suggestions.",
settingsURL: URL(string: UIApplication.openSettingsURLString)!
)
// Still show the basic version of the feature below the banner
- 横幅仅出现 一次,并清晰说明好处。
- 点击后通过
UIApplication.openSettingsURLString打开 设置 → Apple Intelligence & Siri。 - 不能直接深度链接到该子页面,用户需自行导航。
情况 3 – 模型未就绪
在启用后模型下载期间的临时状态。此时应 等待并重试,而不是永久回退。
case .unavailable(.modelNotReady):
showLoadingState(message: "AI features are warming up. This only takes a moment.")
scheduleAvailabilityCheck()
一个简单的重试实现:
func scheduleAvailabilityCheck() {
Task {
try? await Task.sleep(for: .seconds(10)) // 10‑second delay
await checkAndUpdateAvailability()
}
}
在用户停留在页面期间,轮询间隔不应超过每 10–30 秒一次。
整合:清晰的架构
下面是一个最小、可复用的模式,它将所有可用性处理集中起来,并保持 UI 代码整洁。
import FoundationModels
import SwiftUI
// MARK: - Availability State
enum AIAvailabilityState {
case available
case unsupportedDevice
case notEnabled
case modelLoading
}
// MARK: - Feature Manager
@Observable
final class AIFeatureManager {
private(set) var state: AIAvailabilityState = .modelLoading
init() {
refreshAvailability()
}
/// Checks the system availability and updates `state`.
func refreshAvailability() {
switch SystemLanguageModel.default.availability {
case .available:
state = .available
case .unavailable(.deviceNotEligible):
state = .unsupportedDevice
case .unavailable(.appleIntelligenceNotEnabled):
state = .notEnabled
case .unavailable(.modelNotReady):
state = .modelLoading
@unknown default:
state = .modelLoading
}
}
/// Periodically re‑checks availability (used for the “model not ready” case).
func scheduleRecheck() {
Task {
try? await Task.sleep(for: .seconds(15))
await MainActor.run { refreshAvailability() }
}
}
}
// MARK: - SwiftUI View Example
struct AIFeatureView: View {
@StateObject private var manager = AIFeatureManager()
var body: some View {
VStack {
switch manager.state {
case .available:
AIEnabledView() // Your full AI‑powered UI
case .unsupportedDevice:
BasicFeatureView() // Non‑AI fallback
case .notEnabled:
VStack {
BasicFeatureView()
EnableBanner()
}
case .modelLoading:
LoadingView(message: "AI is warming up…")
.onAppear { manager.scheduleRecheck() }
}
}
.animation(.default, value: manager.state) // smooth transitions
}
}
// MARK: - UI Helpers (simplified)
struct EnableBanner: View {
var body: some View {
Button {
if let url = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(url)
}
} label: {
Text("Enable Apple Intelligence in Settings")
.font(.subheadline)
.padding()
.background(Color.blue.opacity(0.1))
.cornerRadius(8)
}
}
}
struct LoadingView: View {
let message: String
var body: some View {
VStack(spacing: 12) {
ProgressView()
Text(message)
.font(.footnote)
.foregroundColor(.secondary)
}
.padding()
}
}
工作原理
AIFeatureManager封装所有系统检查,并公开单一的state值。- SwiftUI 视图根据
state进行响应,展示相应的 UI:- 完整的 AI 功能 (
AIEnabledView) - 基础回退界面 (
BasicFeatureView) - 启用横幅 + 基础 UI (
EnableBanner) - 模型下载中时的加载指示器 (
LoadingView)
- 完整的 AI 功能 (
- 当模型仍在下载时,视图会触发
scheduleRecheck(),在短暂延迟后再次轮询。
你可以在多个屏幕之间复用 AIFeatureManager,甚至在需要相同可用性信息的多个组件中将其包装为 @EnvironmentObject。
TL;DR 检查清单
| 情况 | 显示内容 | 操作 |
|---|---|---|
| 设备不符合资格 | 基本的、非 AI 界面 | 没有提示,仅回退 |
| Apple Intelligence 未启用 | 基本界面 + 一次性横幅,链接到设置 | 提供启用选项,不阻止使用 |
| 模型未就绪 | 加载指示器 + 重试逻辑 | 轮询 SystemLanguageModel.default.availability 直至 .available |
| 一切正常 | 完整的 AI‑驱动界面 | 按预期使用 LanguageModelSession |
通过检测具体的不可用原因并作出相应响应,你可以保持每位用户的体验流畅——无论他们使用的是最新的 iPhone 17 Pro Max 还是 iPhone 12。祝编码愉快!
处理 Apple Intelligence 可用性
当你集成 Apple Intelligence(或任何基础模型)时,会遇到三种可能的 不可用 状态:
| 不可用原因 | 含义 | 常见 UI 响应 |
|---|---|---|
deviceNotEligible | 设备无法运行模型(例如旧 iPhone) | 显示在所有设备上都可用的回退 UI |
appleIntelligenceNotEnabled | 用户已在设置中禁用 Apple Intelligence | 提示用户启用它 |
modelNotReady | 模型仍在设备上加载 | 显示加载指示器并稍后重试 |
下面是使用 SwiftUI 处理这些状态的简洁方法。
1️⃣ 模型层:检测可用性
import SwiftUI
import FoundationModels
final class AIFeatureManager: ObservableObject {
enum State {
case available
case unsupportedDevice
case notEnabled
case modelLoading
}
@Published private(set) var state: State = .unsupportedDevice
init() {
refreshAvailability()
}
func refreshAvailability() {
switch SystemLanguageModel.default.availability {
case .available:
state = .available
case .unavailable(.deviceNotEligible):
state = .unsupportedDevice
case .unavailable(.appleIntelligenceNotEnabled):
state = .notEnabled
case .unavailable(.modelNotReady):
state = .modelLoading
scheduleRetry()
@unknown default:
// Future‑proofing: treat unknown cases as unsupported
state = .unsupportedDevice
}
}
private func scheduleRetry() {
Task {
try? await Task.sleep(for: .seconds(15))
refreshAvailability()
}
}
}
2️⃣ 视图层:渲染正确的 UI
struct SmartFeatureView: View {
@StateObject private var aiManager = AIFeatureManager()
var body: some View {
switch aiManager.state {
case .available:
AIEnhancedView()
case .unsupportedDevice:
BasicFallbackView()
case .notEnabled:
EnablePromptView {
aiManager.refreshAvailability()
}
case .modelLoading:
LoadingView(message: "AI features are getting ready…")
}
}
}
每个状态都有其专用视图,使 UI 简洁且易于维护。当模型可用时,refreshAvailability() 会更新 state,SwiftUI 会自动重新渲染。
您的回退 UI 实际应该做什么
回退并不仅仅是“隐藏 AI 按钮”。它仍应在没有模型的情况下提供价值。以下是常见模式:
| 功能 | 回退方案 |
|---|---|
| 智能文本摘要 | 显示字符计数预览或“显示更多/更少”切换。 |
| 自动标记 / 内容分类 | 让用户手动从精心挑选的标签列表中选择,或使用关键词搜索。 |
| AI 生成的建议 | 提供一组手写的预设选项。 |
| 情境聊天助手 | 切换到 FAQ 风格的界面或帮助文档链接。 |
目标: iPhone 14 用户打开您的应用时应看到一个 可用且有价值 的功能——而不是破碎的屏幕或一大段解释他们的设备为何不够好的文字。
关于 @unknown default 的说明
因为 Apple 的 API 仍在不断演进,始终在 switch 中包含 @unknown default。如果在未来的操作系统版本中出现新的不可用原因,编译器会发出警告,你可以安全地将其视为“未受支持的设备”。
在没有符合条件的设备上进行测试
模拟三种不可用状态的方法如下:
| 状态 | 如何模拟 |
|---|---|
deviceNotEligible | 在较旧的模拟器上运行应用(例如 iPhone 14)。 |
appleIntelligenceNotEnabled | 在受支持的模拟器上,前往 设置 → Apple Intelligence & Siri 并关闭。 |
modelNotReady | 在 AIFeatureManager 中模拟可用性以进行测试。 |
使可用性可模拟
protocol LanguageModelAvailabilityChecker {
var availability: SystemLanguageModel.Availability { get }
}
struct LiveChecker: LanguageModelAvailabilityChecker {
var availability: SystemLanguageModel.Availability {
SystemLanguageModel.default.availability
}
}
struct MockChecker: LanguageModelAvailabilityChecker {
var availability: SystemLanguageModel.Availability
}
在生产环境中注入 LiveChecker,在单元测试中注入 MockChecker。 这样即可在没有实体设备的情况下验证每种可用性状态下的 UI 行为。
更大的图景
优秀的应用将基础模型视为 渐进式增强——它们在提升高性能设备体验的同时,仍能在旧硬件上完美运行。
- 首先构建基线(回退 UI)。
- 在基线稳固后叠加智能。
要求
- iOS 26+
- Xcode 26+
Apple Intelligence 兼容设备
- iPhone 15 Pro / Pro Max
- 所有 iPhone 16 和 iPhone 17 机型
编码愉快! 🎉