App Intentsチュートリアル - Part 1 インテントとパラメータ
WWDC22の "Dive into App Intents" (Appインテントの詳細) というセッションで、読書アプリにApp Intentsを実装していく事例があり、具体的で非常にわかりやすかったので、記事としてまとめてみました。
本記事「Part 1」では、読書アプリの特定のタブを素早く開くインテントの実装を通して、App Intentsの基礎について解説します。
アプリの説明
「読みたい本(Want to Read)」「読んだ本(Read)」「現在読んでいる本(Currently Reading)」を記録するアプリ。
アプリには3つのタブがあり、それぞれのリストを "Shelf" とセッション内では呼んでいる。
特定のタブを素早く開くインテント
Appインテントを公開して、ユーザーがよく開く「現在読んでいる本」のShelfをより素早く、より便利に開けるようにします。
struct OpenCurrentlyReading: AppIntent {
static var title: LocalizedStringResource = "Open Currently Reading"
@MainActor
func perform() async throws -> some IntentResult {
Navigator.shared.openShelf(.currentlyReading)
return .result()
}
static var openAppWhenRun: Bool = true
}
-
AppIntent
プロトコルに準拠した Swiftの構造体を 定義することでOpenCurrentlyReading
インテントをここに作成します - 実装が必要なメソッドは
perform
メソッドだけです- Appには タブを開く
Navigator
がすでにあるため 私にとっての インテントの実装は 数行のコードのみです -
Navigator
はメインスレッド を想定しているためperform
メソッドに@MainActor
の アノテーションを付けます
- Appには タブを開く
- インテントには タイトルも必要です
- キーをstringsファイルに 追加すると自動的に ローカライズされます
ここまでがAppインテントのために 必要な基本的な実装です。
コードで定義されたので ショートカットエディタに 自動的に表示されます。
そこで ユーザーが ショートカットに追加できます
このインテントを公開するだけで 大きな効果が得られます。
ユーザーがこのインテントを ショートカットにすれば システムの様々な場所から インテントが 使用可能になるからです。
ショートカットのサポート
この新しいインテントを簡単に使え、見つけられるようにAppショートカットのサポートを追加します。
少しのコードでSpotlightやショートカットAppにインテントを自動的に表示させることができます。またSiriに対する音声経由でこのインテントを使うためのフレーズも定義する ことができます。
struct LibraryAppShortcuts: AppShortcutsProvider {
static var appShortcuts: [AppShortcut] {
AppShortcut(
intent: OpenCurrentlyReading(),
phrases: ["Open Currently Reading in \(.applicationName)"],
systemImageName: "books.vertical.fill"
)
}
}
すべての詳細につきましては 「Appインテントによる Appショートカットの実装」 セッションをご確認ください。
パラメータの追加: どのタブでも開けるようにする
インテントを公開して 現在読んでいる本の Shelfを開きます。次に これを一般化して
どのShelfにも開けるように パラメータを追加しましょう
enum Shelf: String {
case currentlyReading
case wantToRead
case read
}
- Shelfを表す enumがあります
- パラメータとして 使用するために AppEnumプロトコルに 対応させる必要がありますが、AppEnumには StringのRawデータが 必要であるため まず最初に(この定義を)追加します
extension Shelf: AppEnum {
static var typeDisplayRepresentation: TypeDisplayRepresentation = "Shelf"
static var caseDisplayRepresentations: [Shelf: DisplayRepresentation] = [
.currentlyReading: "Currently Reading",
.wantToRead: "Want to Read",
.read: "Read",
]
}
-
各enumのケースには ローカライズ可能で 人が認識できるタイトルを 付ける必要があります
- コンパイラはビルド時に このコードを読むため これらは辞書リテラル として提供される必要があります
-
最後に typeDisplayName を追加します
- これは この列挙型全体に対する ユーザから見える ローカライズ可能な名前です
- 「Shelf」を 使用します
インテントでは 各パラメータは @Parameter
プロパティ ラッパーで宣言され タイトルなどの パラメータに対する 情報で初期化されます。
struct OpenShelf: AppIntent {
static var title: LocalizedStringResource = "Open Shelf"
@Parameter(title: "Shelf")
var shelf: Shelf
@MainActor
func perform() async throws -> some IntentResult {
Navigator.shared.openShelf(shelf)
return .result()
}
static var parameterSummary: some ParameterSummary {
Summary("Open \(\.$shelf)")
}
static var openAppWhenRun: Bool = true
}
ここでは perform
メソッドで読み込む 新しい shelf
パラメータ を定義します。
パラメータは 数値 文字列 ファイルなどの他にも
エンティティや 列挙型など これらすべての型に 対応しています
このインテントをショートカット エディタで表示するとこのようになります
Shelfパラメータは テーブルに示されています。
パラメータサマリ
ParameterSummary APIを使うことで UIをより合理的にし ショートカットにうまく 適合できます
パラメータサマリは 「Open 」 のように エディタ内でインテントと そのパラメータを表す文章表現です
ショートカットのベストな 結果のためにも 作成する すべてのインテントで
パラメータサマリを 常に提供することをお勧めします。
どのパラメータを下に表示 または非表示にするか 定義することができます。
これらのAPIには WhenとOtherwise API またはSwitch Case Default APIを使用して インテントの任意のパラメータ の実際の値に基づいて サマリを変化させるなど
優れた機能があります。
パラメータサマリ を追加するために
このstaticプロパティ を実装します。
ここでは文字列 「Open」を返し shelfパラメータを 補間します。
アプリを開くインテント
OpenShelf
を 機能させるために 最後に必要なことは、このように インテントを実行すると
読書Appが 開くようにすることです。
Appの起動は static
プロパティ openAppWhenRun
で管理します。
デフォルトはfalse
ですが、この値をtrue
に 設定することで、このようにUIで 何かを開くインテントを実現できます。
次のステップ
「Part 2」では、エンティティとクエリを用いて読書アプリに
- ユーザーが選択した本を開くインテント
- ライブラリに本を追加するインテント
- 「ライブラリに本を追加し、その本を開く」というインテント連携
といった体験の実装方法について学びます。
ひとりアドベントカレンダーやってます!
こちらはひとりで全日埋めるアドベントカレンダー iOS by shu223 - Qiita Advent Calendar 2024 - Qiita の2日目の記事です。がんばって完走目指すので、カレンダーの購読や記事のLikeをポチッとしていただけると嬉しいです。
Discussion