WWDC Quick Look 💓 By SwiftGGTeam
Spotlight your app with App Shortcuts

Spotlight your app with App Shortcuts

观看原视频

Highlight

iOS 17 的 App Shortcuts 让应用功能在安装后立即可用,无需用户手动设置,支持通过 Siri 语音触发、Spotlight 搜索展示和 Shortcuts 应用自动化,同一套代码还能扩展到 Apple Watch 和 HomePod。

核心内容

为什么需要 App Shortcuts

在 iOS 15 及之前,用户必须先打开 Shortcuts 应用或使用”添加到 Siri”按钮来设置快捷指令。这个门槛让很多人望而却步。

App Shortcuts 解决了这个问题:应用安装后自动可用,零配置。用户可以通过三种方式触发:

  • 对 Siri 说出触发短语
  • 在 Spotlight 搜索中看到并点击
  • 在 Shortcuts 应用中组合成更复杂的自动化流程

00:48

基础实现:创建待办列表

实现 App Shortcut 只需要两步:定义 App Intent 和定义 App Shortcut。

import AppIntents

// 第一步:定义 App Intent
struct CreateListIntent: AppIntent {
    static var title: LocalizedStringResource = "Create List"
    
    @Parameter(title: "List Name")
    var listName: String
    
    func perform() async throws -> some IntentResult & ReturnsValue {
        // 实际创建列表的逻辑
        let newList = TodoList(name: listName)
        try await TodoStore.shared.createList(newList)
        
        return .result(
            value: newList,
            dialog: "Created list \(listName)"
        )
    }
}

// 第二步:定义 App Shortcut
struct DemoAppShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: CreateListIntent(),
            phrases: [
                "Create a list in \(.applicationName)",
                "Make a new list with \(.applicationName)"
            ],
            shortTitle: "Create List",
            systemImageName: "plus.square"
        )
    }
}

关键点:

  • 每个应用最多只有一个 AppShortcutsProvider
  • AppShortcut 包含 intent、Siri 触发短语、短标题和系统图标
  • 可以为一个 shortcut 定义多个触发短语
  • 使用 \(.applicationName) 代替硬编码应用名,支持同义词识别

03:29

进阶:Entity 和 Query

当 shortcut 需要引用应用内的具体对象时,需要定义 Entity 和 Query。

import AppIntents

// Entity:应用中的概念对象
struct TodoList: AppEntity {
    let id: UUID
    let name: String
    
    static var typeDisplayRepresentation: TypeDisplayRepresentation {
        "Todo List"
    }
    
    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(
            title: "\(name)",
            image: .init(systemName: "list.bullet")
        )
    }
    
    static var defaultQuery = TodoListQuery()
}

// Query:帮助系统查找实体
struct TodoListQuery: EntityQuery {
    func entities(for identifiers: [TodoList.ID]) async throws -> [TodoList] {
        identifiers.compactMap { TodoStore.shared.list(withID: $0) }
    }
    
    func suggestedEntities() async throws -> [TodoList] {
        TodoStore.shared.recentLists()
    }
}

// 使用 Entity 作为参数的 Intent
struct SummarizeListIntent: AppIntent {
    static var title: LocalizedStringResource = "Summarize List"
    
    @Parameter(title: "List")
    var list: TodoList
    
    func perform() async throws -> some IntentResult & ReturnsValue {
        let summary = await TodoStore.shared.summarize(list: list)
        return .result(
            value: summary,
            dialog: "\(list.name) has \(summary.pendingCount) pending items"
        )
    }
}

关键点:

  • AppEntity 需要实现 idtypeDisplayRepresentationdisplayRepresentation
  • Entity 在 Spotlight 中展示需要 image 或 symbol
  • EntityQuerysuggestedEntities 控制推荐内容
  • entities(for:) 用于按标识符检索具体实例

04:42

带参数的 App Shortcut

struct DemoAppShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: SummarizeListIntent(),
            phrases: [
                "Summarize my \(list) with \(.applicationName)",
                "What's in my \(list) in \(.applicationName)",
                "Summarize a list with \(.applicationName)"  // 不带参数的版本
            ],
            shortTitle: "Summarize List",
            systemImageName: "text.magnifyingglass"
        )
    }
}

关键点:

  • 短语中可以用 \(parameterName) 引用参数
  • 提供不带参数的版本,让 Siri 可以在用户未指定时提示选择
  • 每次实体数据变化后调用 updateAppShortcutParameters()
  • 首次启动时也要调用,否则带参数的短语无法工作

07:40

详细内容

iOS 17 新特性:Flexible Matching

iOS 16 中,Siri 只识别完全匹配的触发短语。iOS 17 引入了 Semantic Similarity Index,支持语义相似的短语自动匹配。

// 定义了这句话
"Summarize my groceries list with Demo"

// iOS 17 中这些也能自动匹配,无需额外代码
"Tell me the summary of my groceries list with Demo"
"Give me a summary of my shopping list with Demo"

关键点:

  • 用 Xcode 15 重新编译即可启用,无需代码改动
  • 可以在 Build Settings 中关闭 “Enable App Shortcuts Flexible Matching”
  • 新增 synonyms API 为 Entity 实例定义别名

14:24

同义词和 Negative Phrases

extension TodoList {
    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(
            title: "\(name)",
            synonyms: ["shopping", "grocery list"]
        )
    }
}

struct DemoAppShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: SummarizeListIntent(),
            phrases: ["Summarize my \(list) with \(.applicationName)"],
            shortTitle: "Summarize List",
            systemImageName: "text.magnifyingglass",
            negativePhrase: "Send a Demo summary to my grocery store"
        )
    }
}

关键点:

  • synonyms 让用户可以用不同名称指代同一实体
  • negativePhrase 防止不相关的句子误触发 shortcut
  • 同义词变化后需要调用 updateAppShortcutParameters()

15:17

App Shortcuts Preview 工具

Xcode 15 引入了 App Shortcuts Preview,无需运行应用即可测试 Siri 短语。

使用方式:

  1. Product > App Shortcuts Preview
  2. 先编译应用生成 Semantic Similarity Index
  3. 在左侧选择应用,输入测试短语
  4. 支持切换 locale 测试多语言

这个工具大幅缩短了调试周期,特别是测试多语言场景时不再需要切换设备语言。

16:25

String Catalog 本地化

iOS 17 解除了每个 locale 触发短语数量的限制。使用 String Catalog 管理本地化:

// 创建 AppShortcuts.xcstrings
// 编译后自动从 AppShortcutsProvider 提取短语
// 可以为每个 locale 添加任意数量的额外短语

关键点:

  • 新应用直接创建名为 “AppShortcuts” 的 String Catalog
  • 已有应用将 AppShortcuts.strings 迁移到 String Catalog
  • 只有 targeting iOS 17+ 的应用才能使用此功能

18:41

跨设备支持

Apple Watch

  • App Shortcuts 必须来自安装在手表上的 watchOS 应用
  • iOS 应用的 shortcut 不能在 Watch 上运行
  • 不支持 Flexible Matching,短语必须完全匹配

HomePod

  • 需要 companion iOS/iPadOS 设备上安装支持 App Shortcuts 的应用
  • HomePod 上可能完全不启动应用
  • 返回的 dialog 需要清晰简洁,因为 HomePod 是纯语音设备
// 为 HomePod 提供完整的语音描述,为视觉设备提供简洁版本
IntentDialog(
    full: "Your groceries list has 5 pending items: milk, eggs, bread, apples, and coffee",
    supporting: "5 items pending"
)

22:05

核心启发

  • 做什么:为核心功能创建零配置的语音入口

    • 为什么值得做:App Shortcuts 安装后自动可用,无需用户手动设置,大幅降低使用门槛
    • 怎么开始:为每个核心功能创建 AppIntent,在 AppShortcutsProvider 中定义触发短语,用 \(.applicationName) 支持同义词
  • 做什么:在 Spotlight 中展示应用实体

    • 为什么值得做:Spotlight Top Hits 会展示应用的 App Shortcuts,用户搜索应用名时直接看到可用操作
    • 怎么开始:为应用内对象定义 AppEntity,实现 displayRepresentation 时包含 image 或 symbol,实现 suggestedEntities 控制推荐内容
  • 做什么:实现上下文感知的 Siri 提示

    • 为什么值得做:用户在应用内看到 Siri Tip 时,更容易记住并使用语音控制
    • 怎么开始:在相关界面添加 SiriTipView,使用 SwiftUI 和 UIKit 都支持,放在与内容相关的位置
  • 做什么:为 Apple Watch 和 HomePod 扩展语音体验

    • 为什么值得做:同一套 App Intents 代码可以服务多个设备,扩大用户触达面
    • 怎么开始:为 watchOS 应用单独定义 App Shortcuts,为 HomePod 场景返回 IntentDialogfull 版本
  • 做什么:用 App Shortcuts Preview 建立短语测试流程

    • 为什么值得做:手动测试 Siri 短语耗时且难以覆盖多语言场景
    • 怎么开始:在 Xcode 15 中使用 App Shortcuts Preview,为每个 intent 测试标准短语、变体短语和边界情况,导出测试用例供团队成员使用

关联 Session

评论

GitHub Issues · utterances