当 Apple Intelligence 不可用时,如何优雅地回退

发布: (2026年2月21日 GMT+8 08:24)
12 分钟阅读
原文: Dev.to

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 访问权限

即使在符合条件的硬件上,你仍然需要:

  1. 在设置中 启用 Apple Intelligence(需自行选择)
  2. ≥ 7 GB 可用存储空间
  3. 设备和 Siri 语言设置为 受支持的语言
  4. 模型 已完整下载(启用后会在后台下载)

结论: 仅凭操作系统版本较新,不能假设模型可用。

三种不可用情况

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()
    }
}

工作原理

  1. AIFeatureManager 封装所有系统检查,并公开单一的 state 值。
  2. SwiftUI 视图根据 state 进行响应,展示相应的 UI:
    • 完整的 AI 功能 (AIEnabledView)
    • 基础回退界面 (BasicFeatureView)
    • 启用横幅 + 基础 UI (EnableBanner)
    • 模型下载中时的加载指示器 (LoadingView)
  3. 当模型仍在下载时,视图会触发 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 并关闭。
modelNotReadyAIFeatureManager 中模拟可用性以进行测试。

使可用性可模拟

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 行为。

更大的图景

优秀的应用将基础模型视为 渐进式增强——它们在提升高性能设备体验的同时,仍能在旧硬件上完美运行。

  1. 首先构建基线(回退 UI)。
  2. 在基线稳固后叠加智能

要求

  • iOS 26+
  • Xcode 26+

Apple Intelligence 兼容设备

  • iPhone 15 Pro / Pro Max
  • 所有 iPhone 16 和 iPhone 17 机型

编码愉快! 🎉

0 浏览
Back to Blog

相关文章

阅读更多 »

Subnetting 详解

什么是 Subnetting?可以把它想象成把一栋大型公寓楼拆分成不同的楼层。每层 subnet 拥有自己的编号主机(hosts),以及建筑……