struct LogWaterAmountIntent: AppIntent { static var title: LocalizedStringResource = "杯数を指定して水を記録" @Parameter(title: "杯数") var glasses: Int func perform() async throws -> some IntentResult & ProvidesDialog { await WaterStore.shared.add(glasses: glasses) return .result(dialog: "\(glasses)杯を記録しました。") }}
@Parameter の title が、Siri が値を尋ねるときの文言になります。ここを「杯数」のように具体的にしておくと、「何杯ですか」と自然に聞き返してくれます。曖昧な名前にすると、聞き返しの日本語も曖昧になります。
本番で詰まった点とその対処
実機に出してから気づいた、説明書には書かれていない挙動を、詰まった順に挙げます。
ショートカットの登録が即座に反映されないことがあります。AppShortcutsProvider を変更しても、アプリを一度起動し直すまで Siri に伝わらないためです。AppShortcuts.updateAppShortcutParameters() を起動時に呼ぶと反映が早まります。私はここで「フレーズを変えたのに認識されない」と1時間ほど溶かしました。
すべての操作をインテントにする必要はありません。むしろ、入口を増やしすぎると Siri が候補を絞れず、認識精度がかえって落ちます。私が推奨するのは、「一日に何度も繰り返す」かつ「一手で完結する」操作だけを選ぶことです。水の記録のように頻度が高く可逆な操作は、声の入口を用意する価値が大きい一方、設定変更のように稀で複雑な操作は、画面に残したほうが迷いません。
私の判断では、インテントの定義とフレーズ設計は手で書きます。フレーズは日本語の言い回しの機微が絡み、生成任せにすると不自然な言葉が混じりやすいからです。一方で、perform() が呼ぶデータ操作の本体や、結果を表示する画面は Rork Max の生成コードをそのまま使えます。操作を関数として綺麗に切り出してあれば、インテントはその薄い包み紙で済みます。