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

Spotlight your app with App Shortcuts

元の動画を見る

ハイライト

iOS 17 の App Shortcuts により、アプリの機能はインストール直後から手動設定なしで利用可能になります。Siri の音声トリガー、Spotlight 検索での表示、Shortcuts アプリの自動化に対応し、同じコードで Apple Watch と HomePod にも拡張できます。

主要内容

App Shortcuts が必要な理由

iOS 15 以前は、ユーザーが Shortcuts アプリを開くか「Siri に追加」ボタンでショートカットを設定する必要がありました。このハードルが多くの人を遠ざけていました。

App Shortcuts はこれを解決します。インストール後すぐに自動で利用可能で、設定は不要です。ユーザーは 3 つの方法でトリガーできます:

  • Siri にトリガーフレーズを話す
  • Spotlight 検索で表示されタップする
  • Shortcuts アプリでより複雑な自動化に組み合わせる

00:48

基本実装: ToDo リストの作成

App Shortcut の実装は 2 ステップだけです。App Intent を定義し、App Shortcut を定義します。

import AppIntents

// ステップ 1: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)"
        )
    }
}

// ステップ 2: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 は最大 1 つ
  • AppShortcut には intent、Siri トリガーフレーズ、短いタイトル、システムアイコンが含まれる
  • 1 つの 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 の実装が必要
  • Spotlight で表示する Entity には 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 に移行
  • iOS 17 以降をターゲットにするアプリのみこの機能を利用可能

18:41

クロスデバイス対応

Apple Watch:

  • App Shortcuts はウォッチにインストールされた watchOS アプリから提供する必要がある
  • iOS アプリの shortcut は Watch では動作しない
  • Flexible Matching は非対応。フレーズは完全一致が必要

HomePod:

  • コンパニオンの 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 で標準フレーズ・変形・境界ケースをテストし、チーム向けにテストケースをエクスポート

関連セッション

コメント

GitHub Issues · utterances