Dive into App Intents
Swift & UI 进阶 20m

深入 App Intents 框架

Dive into App Intents

2022年6月6日

在 Apple 官方观看视频

一句话判断

App Intents 是 Apple 全新推出的框架,用纯 Swift 定义你的 App 功能,让它自动接入 Siri、Shortcuts、Spotlight 和 Focus Filters——一次实现,全平台可达。

这场 Session 讲了什么

iOS 10 引入的 SiriKit Intents 基于 Objective-C,需要创建单独的 Extension,适配成本高。App Intents 完全重新设计了这套体系:直接在 App 主工程里用 Swift 定义 Intent,不需要 Extension,不需要额外的 framework target。

核心架构分三层:Intent 是一个独立的动作单元(比如”打开当前阅读书架”);Entity 用类型安全的方式表示 App 中的概念(比如”书架”这个枚举);App Shortcut 则包装 Intent 让用户通过 Siri 语音短语直接触发。

演讲者用一个图书管理 App 作为案例,从最简单的”打开当前阅读”Intent 开始,逐步展示如何添加参数、定义 Entity、实现 Parameter Summary(让 Shortcuts 编辑器展示更友好的 UI),以及如何构建支持查找和过滤的 Entity Query。

值得一提的是 App Intents 的设计哲学和 SwiftUI 高度一致:代码即 Source of Truth,不需要单独的编辑器或定义文件,所有配置都在 Swift 代码里完成,编译器在构建时读取这些信息。

值得深挖的点

  • Entity Query 的强大能力:你可以定义 EntityStringQuery,让用户在 Shortcuts 里通过自然语言搜索你的 App 内容。系统会自动处理模糊匹配,你只需要提供字符串比较逻辑。
  • Focus Filters:App Intents 让你的 App 能响应 Focus 模式变化。比如用户设置了工作 Focus,你的 App 可以自动切换到工作相关的数据视图。这是以前做不到的系统级集成。
  • ParameterSummary 的高级用法:可以用 When/OtherwiseSwitch/Case 根据参数值动态改变 Summary 的展示文本,让 Shortcuts 编辑器里的动作描述更加精确。
  • 无需 Extension 的架构:App Intents 直接在 App 进程中运行,减少了 IPC 开销,也让调试变得简单。唯一的代价是 App 需要在后台被唤醒。

代码片段

// 定义一个最简单的 Intent
struct OpenCurrentlyReading: AppIntent {
    static var title: LocalizedStringResource = "Open Currently Reading"

    @MainActor
    func perform() throws -> some IntentResult {
        Navigator.shared.openTab(.currentlyReading)
        return .result()
    }
}

// 定义带参数和 Entity 的 Intent
struct OpenShelf: AppIntent {
    static var title: LocalizedStringResource = "Open Shelf"

    @Parameter(title: "Shelf")
    var shelf: ShelfEntity

    static var parameterSummary: some ParameterSummary {
        Summary("Open \.$shelf")
    }

    @MainActor
    func perform() throws -> some IntentResult {
        Navigator.shared.openTab(shelf.rawValue)
        return .result()
    }
}

// 定义 AppEnum 作为参数类型
enum Shelf: String, AppEnum {
    case currentlyReading, wantToRead, finished

    static var typeDisplayName: LocalizedStringResource = "Shelf"
    static var caseDisplayRepresentations: [Shelf: DisplayRepresentation] = [
        .currentlyReading: "Currently Reading",
        .wantToRead: "Want to Read",
        .finished: "Finished"
    ]
}

最佳实践

  • 每个 Intent 只做一件事,保持单一职责
  • 始终为 Intent 提供 parameterSummary,这决定了它在 Shortcuts 编辑器中的展示效果
  • @MainActor 标注需要主线程执行的 Intent perform 方法
  • 为 Entity 提供有意义的 displayRepresentation,用户在 Spotlight 和 Shortcuts 中看到的就是这些文本
  • 利用 preferOnlineAuthentication 让需要网络的 Intent 在离线时优雅降级

还有什么值得关注

  • 搭配 “Implement App Shortcuts with App Intents” 学习如何定义 Siri 语音短语
  • “Design App Intents for everyone” 讲解了 Intent 的设计规范和可访问性要求
  • App Intents 是 Shortcuts 未来发展的核心方向,老版 IntentKit 不会立即废弃,但新功能只会出现在 App Intents 中
  • 如果你的 App 已经用了 SiriKit,可以逐步迁移,两套框架可以共存
WWDC 2022