Bring your app's core features to users with App Intents
SwiftUI & UI Frameworks 进阶 20m

用 App Intents 把应用核心功能带到用户面前

Bring your app's core features to users with App Intents

2024年6月10日

在 Apple 官方观看视频

一句话判断

App Intents 不是某一个功能,而是 Siri、Spotlight、Shortcuts、Widgets、Control Center 等全系系统体验的统一底座——写一次 Intent,你的应用功能就能渗透到设备的每个角落。

这场 Session 讲了什么

这场 Session 是 App Intents 的入门总览,面向还没有接触过这个框架的开发者。主讲人 Christopher Nebel 用一个徒步路线 App 做贯穿全场的 demo,展示了如何让你的应用功能不再困在”方块图标”里。

核心理念是”减少摩擦”(friction)。用户在多个 App 之间切换本身就是一种摩擦。如果系统能理解你 App 里的核心动作和内容,就可以把它们直接展示在 Spotlight、Siri、Widget、Control Center 里,用户不需要打开你的 App 就能完成操作。App Intents 就是实现这一切的统一协议层——你定义好 Intent(动作)、Entity(对象)、App Shortcut(预设快捷方式),系统各处就能自动消费这些定义。

Session 的后半段演示了具体实现:从定义一个 OpenTrailIntent 到让它在 Spotlight Suggestions 中出现,再到用 Entity 让 Siri 理解”我的收藏路线”这类自然语言指令。整个过程不需要为每个系统功能写单独的集成代码,App Intents 做了统一的通信管道。

值得深挖的点

App Intents 的三层抽象:Intent、Entity、App Shortcut

这三个概念构成了一个类似”动词-名词-句子”的语法体系。Intent 是动词,比如”打开路线”或”开始徒步”。Entity 是名词,比如”路线”或”合集”。App Shortcut 则是把动词和名词打包成一句话,代表你 App 里最核心的功能。

这种设计的精妙之处在于复用性。你定义一个 TrailEntity,所有需要引用路线的 Intent 都能共享它。你定义一个 OpenTrailIntent,它在 Spotlight、Siri、Shortcuts 里都能被触发。过去开发者要分别对接 SiriKit、NSUserActivity、CSSearchableItem 等不同 API,现在一套代码覆盖所有场景。

Trade-off 也很明显:App Intents 要求你用 Swift 的 @AssistantIntent 宏来声明式地定义意图,这套 DSL 有学习曲线,而且编译时的类型检查会比较严格。但换来的是跨场景的零成本复用,以及 Apple Intelligence 时代 Siri 对你 App 内容的深度理解。

“Flow” 的设计哲学

Session 反复强调 flow(心流)这个概念,不只是心理学层面的”沉浸感”,更是设备层面的”最小路径”。用户想到一件事到完成这件事之间的步骤越少,体验就越好。App Intents 让你的 App 不再是一个孤岛,而是变成设备体验的一部分。对于用户粘性来说,这意味着用户不需要”进入”你的 App 才能感受到它的价值——Widget 展示实时信息、Spotlight 快捷操作、Siri 语音指令,都在持续强化你和用户之间的连接。

代码片段

定义一个简单的 App Intent

struct OpenTrailIntent: AppIntent {
    static var title: LocalizedStringResource = "Open Trail"
    static var description = IntentDescription("Opens a specific trail in the app")

    @Parameter(title: "Trail")
    var trail: TrailEntity

    func perform() async throws -> some IntentResult {
        // 导航到指定路线的详情页
        Navigator.shared.open(trail)
        return .result()
    }
}

一句话说明:这是最基本的 Intent 定义,@Parameter 让 Siri 知道需要用户提供哪个路线,perform() 是实际执行逻辑。坑在于 title 必须用 LocalizedStringStringResource,普通的 String 不行。

定义 Entity 让系统理解你的数据模型

struct TrailEntity: AppEntity {
    static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "Trail")
    static var defaultQuery = TrailEntityQuery()

    var id: UUID
    var name: String
    var difficulty: TrailDifficulty

    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(title: "\(name)")
    }
}

一句话说明:Entity 是你的数据模型在系统层面的投影,defaultQuery 负责让 Siri 能搜索和匹配你的数据。别忘了实现 EntityQuery,否则 Siri 无法解析用户说的”那条我收藏的路线”。

注册 App Shortcut 让功能出现在 Spotlight

struct TrailShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: OpenTrailIntent(),
            phrases: [
                "Open \(.applicationName)",
                "Show my trail in \(.applicationName)"
            ],
            shortTitle: "Open Trail",
            systemImageName: "figure.hiking"
        )
    }
}

一句话说明:phrases 数组定义了 Siri 语音触发短语,也是 Spotlight Suggestions 展示的依据。短语要尽量口语化,不要写技术术语。

最佳实践

新项目:从第一天就把 App Intents 纳入架构设计。数据模型直接用 AppEntity 协议来定义,核心操作用 AppIntent 封装。这样你在做 Widget、Control Center 扩展时几乎零额外成本。

已有项目:不要试图一次迁移所有功能。先挑 1-2 个最高频操作(比如”打开最近使用的文档”、“标记收藏”),把它们做成 App Shortcut。这些最容易在 Spotlight 和 Siri 中暴露给用户,立竿见影。之后再逐步扩展 Entity 和 Intent 的覆盖范围。

两个通用原则:第一,App Shortcut 的数量不要贪多,每个 Shortcut 应该是你 App 的核心价值入口;第二,Entity 的 displayRepresentation 要花时间打磨,它直接决定了 Siri 向用户展示时的可读性。

还有什么值得关注

  • Control Center 自定义控件今年也基于 App Intents,你的 Intent 加上 WidgetConfigurationIntent 就能变成 Control Center 里的按钮。
  • Action Button 和 Apple Pencil Pro 的 squeeze 手势同样消费 App Intents,硬件交互的软件层也是统一的。
  • Apple Intelligence 的 Siri 重大升级底层就是依赖 App Intents 提供的结构化数据,越早接入,Siri 对你 App 的理解越深。
WWDC 2024