ハイライト
App Intents は Siri、Spotlight、Shortcuts、Widget、Control Center などすべてのシステム統合の統一プロトコル層——Intent、Entity、Query を 1 回定義すれば、複数のシステム入口を同時に駆動できます。
主要内容
App がどれだけ優れていても、ユーザーが開かなければ何も見えません。Christopher Nebel は冒頭で率直な比喩を使います。各 App は丁寧に作られた「箱」で、箱の中の体験は完璧ですが、箱同士を行き来すること自体が摩擦(friction)です。App の切り替えには時間と注意力が必要で、この小さな摩擦が繰り返されるとユーザーの操作フロー(flow)が途切れます。
App Intents が解決するのはこの問題です。システムが App 内の中核的なアクションとコンテンツオブジェクトを理解し、Spotlight 検索提案、Siri 会話、ホーム画面 Widget、Control Center コントロール、Action Button、Apple Pencil Pro のスクイーズなどに直接表示します。ユーザーは App を開かずに重要な操作を完了できます。セッション全体をハイキングルート App でデモ:最もシンプルな OpenPinnedTrailIntent から始め、パラメータ付き Intent、設定可能 Widget、Control Center ボタン、App Shortcut へ段階的に拡張。同一の Entity と Query が異なる機能間で再利用される様子を示します。
重要な洞察はコード再利用です。OpenTrail Intent 用に定義した TrailEntity と TrailEntityQuery は、Widget の設定パラメータ、Control Center のボタン設定、Siri の自然言語インタラクションで直接使用可能。1 回書けば、どこでも効く。
詳細
Intent:アクションの定義(09:31)
Intent は AppIntent プロトコルに準拠する型で、2 つを提供する必要があります:title(ローカライズされたタイトル。Shortcuts ではアクション名として表示)と perform() メソッド(実際の操作を実行)。
struct OpenPinnedTrailIntent: AppIntent {
static var title: LocalizedStringResource = "Open Pinned Trail"
static var openAppWhenRun = true
func perform() throws -> some IntentResult {
// ピン留めされたルート詳細ページへ移動
TrailNavigator.navigateToPinnedTrail()
return .result()
}
}
キーポイント:
titleはローカライズ文字列。Shortcuts App ではそのままアクション名openAppWhenRun = trueで実行時に App をフォアグラウンドに開くperform()はIntentResultを返す。ここでは.result()のみ(ページ遷移だけで十分)- Intent 名はユーザーが理解できるアクション(OpenPinnedTrail)。内部実装名は使わない
Entity + Query:コンテンツと検索ロジック(12:13)
Entity は App 内の「名詞」——中核的なコンテンツオブジェクト。AppEntity プロトコルに準拠し、displayRepresentation(表示用)、id(永続識別子)、query(クエリオブジェクト)を提供。
struct TrailEntity: AppEntity {
static var typeDisplayRepresentation = TypeDisplayRepresentation(name: "Trail")
static var defaultQuery = TrailEntityQuery()
var id: UUID
var name: String
var displayRepresentation: DisplayRepresentation {
DisplayRepresentation(title: "\(name)")
}
}
Query は 2 つの質問に答えます:選択可能な Entity は?特定 ID に対応する Entity は?最もシンプルな方法は EnumerableEntityQuery に準拠し、allEntities() を提供:
struct TrailEntityQuery: EntityQuery, EnumerableEntityQuery {
func allEntities() async throws -> [TrailEntity] {
// すべてのルートを返す。データ量をすべてメモリに読み込める場合に適している
TrailStore.shared.allTrails.map { trail in
TrailEntity(id: trail.id, name: trail.name)
}
}
func entities(for identifiers: [UUID]) async throws -> [TrailEntity] {
// ID に基づいて検索し、Intent 実行時にパラメータを復元するために使う
allEntities().filter { identifiers.contains($0.id) }
}
}
キーポイント:
- iOS 18 SDK でビルドすると、
EnumerableEntityQueryから検索、述語クエリなどより複雑なクエリプロトコルを自動派生可能(14:18) - データ量が大きくメモリに全部載せられない場合は
EntityStringQueryなど他のサブプロトコルに切り替え - Query の
entities(for:)で Intent 実行時に保存された ID を完全な Entity オブジェクトに復元。Intent コードは裸の ID ではなく Entity を取得
パラメータ付き Intent:OpenIntent(11:04)
Intent がユーザー選択のコンテンツオブジェクトを受け取る必要がある場合、OpenIntent プロトコルを使用:
struct OpenTrailIntent: OpenIntent {
static var title: LocalizedStringResource = "Open Trail"
@Parameter(title: "Trail")
var target: TrailEntity
func perform() throws -> some IntentResult {
TrailNavigator.navigateToTrail(id: target.id)
return .result()
}
}
キーポイント:
OpenIntentはopenAppWhenRunを暗黙的に含む。手動宣言不要@Parameterマークのプロパティは Shortcuts のパラメータ選択 UI に自動表示。Query が候補を提供- パラメータ型は Entity 自体(
TrailEntity)。Entity を記述するデータ(trail name や UUID)ではない
Parameter Summary:Shortcuts で読みやすい操作説明(15:00)
static var parameterSummary: some ParameterSummary {
Summary("Open \.$target")
}
キーポイント:
- parameterSummary がないと Shortcuts ではパラメータがリスト下部に折りたたまれ読みにくい
- 追加すると「Open Monterey Bay Coastal Trail」のような自然言語文として表示
- ユーザーがパラメータを編集するとプレースホルダーがリアルタイムで置換され、操作意図が一目瞭然
Widget と Control Center:既存 Entity の再利用(16:59)
Widget の設定 Intent は WidgetConfigurationIntent に準拠。以前定義した TrailEntity をパラメータ型として直接再利用。Control Center の設定可能コントロールも同様に ControlConfigurationIntent プロトコルを使用:
extension OpenTrailIntent: ControlConfigurationIntent {}
// 空の extension。OpenTrailIntent は必要なものをすでに備えている
キーポイント:
- 1 つの Intent が複数の設定プロトコルに同時準拠可能。Widget と Control Center 用に別 Intent を書く必要なし
- Control Center ボタンのタップアクションは設定済み Intent インスタンスを直接渡せる。
perform()とパラメータ値を既に持っている
App Shortcut:Spotlight と Siri に自動表示(20:40)
struct TrailAppShortcuts: AppShortcutsProvider {
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: OpenPinnedTrailIntent(),
phrases: [
"Open my pinned trail in \(.applicationName)"
],
shortTitle: "Open Pinned Trail",
systemImageName: "pin.fill"
)
}
}
キーポイント:
- App Shortcut がラップするのは Intent インスタンス(型ではない)。登録時にパラメータを事前入力可能
phrasesには\.applicationNameを必ず含める。Siri が音声指令をマッチするために必要- 手動登録コード不要——フレームワークが
AppShortcutsProviderを自動検出。App インストール後すぐ使用可能 - 既存 App Shortcut は今年 Apple Pencil Pro スクイーズを、昨年 Action Button を自動サポート(22:30)
Dialog + Snippet を返して App を開かない(22:56)
Siri が Intent を実行するとき、ページ操作ではなく情報表示だけなら、Dialog と SwiftUI ビューを含む結果を返して App 遷移を避けられる:
struct ShowPinnedTrailIntent: AppIntent {
static var title: LocalizedStringResource = "Show Pinned Trail Conditions"
func perform() async throws -> some IntentResult & ProvidesDialog & ShowsSnippetView {
let trail = TrailStore.shared.pinnedTrail
return .result(
dialog: "\(trail.name) conditions: \(trail.conditions)",
view: TrailConditionsView(trail: trail)
)
}
}
キーポイント:
ProvidesDialogで Siri がテキストを読み上げ、ShowsSnippetViewで画面上に SwiftUI スニペットを表示- Dialog とビューテキストは異なってよい。読み上げ版と視覚版でそれぞれ重点を置ける
- ビューは Widget と同じアーカイブ機構。Widget がサポートする SwiftUI 機能のみ使用可能
- ユーザーは Snippet を見た後その場に留まり、App に飛ばされない
重要ポイント
-
やること:中核コンテンツモデルに
AppEntity+EntityQueryを定義。理由:Entity はすべての App Intents 機能の基盤。1 回定義すれば Shortcuts パラメータ選択、Widget 設定、Control Center 設定、Siri の自然言語理解がすべて自動でサポートされ、以降の拡張コストはゼロ。始め方:App で最も中核的な 1〜2 データモデルを選び、AppEntityに準拠。displayRepresentation、id、EnumerableEntityQueryを実装。 -
やること:最高頻度の操作を App Shortcut に。理由:App Shortcut はインストール即生效。Spotlight 提案と Siri に自動表示。ユーザー設定不要で中核機能に到達——ROI 最高の統合方式。始め方:最もよく使う 1〜2 操作(「最近のドキュメントを開く」「お気に入りを表示」など)を見つけ、
AppShortcutsProviderで App Shortcut にラップ。phrases と shortTitle を書く。 -
やること:同じ Intent で複数のシステム入口を駆動。理由:セッションの
OpenTrailIntentが Shortcuts アクション、Widget 設定、Control Center ボタン、Siri 指令の底层実装として同時に機能。コードは 1 回だけ。1 つの Intent が複数プロトコル(OpenIntent+WidgetConfigurationIntent+ControlConfigurationIntent)に準拠すれば全シーンをカバー。始め方:既存 SiriKit Intent やカスタム URL Scheme 処理を App Intent に統一移行し、プロトコル拡張で Widget と Control Center を段階的に接続。
関連セッション
- Designing App Intents — Siri、Shortcuts、Spotlight など各所で良好に動作する App Intent の設計方法
- Bring your app to Siri — App Intents と Siri 統合の詳細
- What’s new in App Intents — 2024 年 App Intents フレームワークの最新更新
- Explore enhancements to App Intents — WWDC23 の Widget 設定と Entity Query 強化の詳解
コメント
GitHub Issues · utterances