Implement App Shortcuts with App Intents
Swift & UI 进阶 20m

用 App Intents 实现 App Shortcuts

Implement App Shortcuts with App Intents

2022年6月6日

在 Apple 官方观看视频

一句话判断

从 SiriKit 到 App Intents 的范式转移——纯 Swift 定义、零代码生成、安装即可用,这场 Session 是实现 App Shortcuts 的工程手册。

这场 Session 讲了什么

Apple 工程师 Michael Sumner 以一个冥想应用为例,演示了如何用全新的 App Intents 框架构建 App Shortcuts。旧方案(SiriKit + Intents 框架)需要单独的 metadata 文件、代码生成步骤、以及用户手动添加到 Siri。新方案中,一切都在 Swift 源码中声明,安装后自动可用。

Session 覆盖了三个阶段:基础 Intent 创建与 AppShortcut 注册、参数化 Intent 的实现、以及自定义 SwiftUI 视图在 Siri 结果中的展示。

值得深挖的点

App Intents 框架的设计哲学。所有定义都在 Swift 代码中完成,不需要 .intentdefinition 文件,不需要代码生成。这意味着代码审查更直观,合并冲突更容易解决,开发流程更流畅。作为一个 Swift-only 框架,它充分利用了 async/await、结构体、协议等现代 Swift 特性。

AppIntent 协议的最小实现。只需要两个东西:一个 title(String)和一个 perform() 方法(async throws)。perform() 方法可以调用异步代码、触发用户提示、返回结果对话框。整个实现非常精简。

自定义视图的约束。App Intent 的自定义视图基于 SwiftUI,技术上跟 Widget 共享同一套视图技术。这意味着不需要单独的 UI Extension。但约束也很明确:不支持交互性(interactivity)和动画。视图适合展示确认信息、结果摘要,不适合做复杂交互。

三个展示自定义 UI 的时机:值确认(value confirmation)、意图确认(intent confirmation)、以及 Intent 执行完成后。开发者需要根据业务场景选择合适的时机。

代码片段

// 最小化的 App Intent 实现
struct StartMeditationIntent: AppIntent {
    // 标题,用于 Shortcuts app 中展示
    static var title: LocalizedStringResource = "开始冥想"
    
    // 参数摘要,自定义在 Shortcuts 中的渲染外观
    static var description = IntentDescription("开始一段冥想会话")
    
    // 核心执行逻辑
    func perform() async throws -> some IntentResult & ReturnsValue<Bool> {
        // 调用应用服务启动冥想
        try await MeditationService.shared.startDefaultSession()
        // 返回给用户的对话框
        return .result(
            dialog: "冥想已开始,放松身心吧",
            value: true
        )
    }
}

// AppShortcutsProvider 注册
struct MeditationAppShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: StartMeditationIntent(),
            phrases: [
                "Start a \(.applicationName)",
                "开始\(.applicationName)"
            ],
            shortTitle: "开始冥想",
            systemImageName: "brain.head.profile"
        )
    }
}

// 带自定义视图的返回
func perform() async throws -> some IntentResult & ProvidesCustomView {
    let session = try await MeditationService.shared.startDefaultSession()
    return .result(
        dialog: "冥想已开始",
        view: MeditationResultView(session: session)
    )
}

最佳实践

  • .applicationName token 会自动匹配应用的官方名称和所有注册的别名,不要硬编码应用名
  • 如果 Intent 会触发应用启动(openAppWhenRun),它不会出现在 Spotlight 结果中——区分”轻量级完成”和”需要打开应用”的场景
  • 参数摘要(Parameter Summary)能显著提升 Shortcuts app 中的可读性,为你的 Intent 添加它
  • 本地化所有用户可见的字符串,包括 title、dialog 和 phrases
  • 最多注册 10 个 App Shortcut,但大多数应用只需要 2-5 个

还有什么值得关注

  • App Intents 框架同时是 WidgetKit 和 Siri Suggestions 的底层,投资学习这个框架的回报是复合的
  • 自定义视图跟 Widget 共享技术栈,可以考虑复用 Widget 的视图代码
  • Spotlight 只展示第一个注册的 App Shortcut,顺序很重要
  • 对于需要用户输入的场景,可以用 requestValue(from:) 触发系统级的值输入 UI
  • App Intents 的 discoverability 还通过 Spotlight Suggestions 和 Siri Suggestions 自然增强
WWDC 2022