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需要实现id、typeDisplayRepresentation和displayRepresentation- Entity 在 Spotlight 中展示需要 image 或 symbol
EntityQuery的suggestedEntities控制推荐内容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”
- 新增
synonymsAPI 为 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 短语。
使用方式:
- Product > App Shortcuts Preview
- 先编译应用生成 Semantic Similarity Index
- 在左侧选择应用,输入测试短语
- 支持切换 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 场景返回
IntentDialog的full版本
-
做什么:用 App Shortcuts Preview 建立短语测试流程
- 为什么值得做:手动测试 Siri 短语耗时且难以覆盖多语言场景
- 怎么开始:在 Xcode 15 中使用 App Shortcuts Preview,为每个 intent 测试标准短语、变体短语和边界情况,导出测试用例供团队成员使用
关联 Session
- Explore enhancements to App Intents — App Intents 框架在 iOS 17 中的全面增强
- Integrate your media app with HomePod — 将媒体应用与 HomePod 集成
- Design App Shortcuts — App Shortcuts 的设计指南
- Migrate custom Intents to App Intents — 将 SiriKit Intents 迁移到 App Intents
评论
GitHub Issues · utterances