-
Code Along:アプリをSiriに対応させる方法
アプリをSiriに対応させる方法をお見せしつつ、Xcodeプロジェクトを詳細に解説します。App Schemaを導入すると、ユーザーがカレンダーイベントについて質問したり、スケジュール作成などの自然言語によるアクションを実行したりできるようになります。Spotlightのセマンティックインデックスにコンテンツを対応させ、オンスクリーン認識のためのコンテキストを提供する上でのベストプラクティスを紹介します。
関連する章
- 0:00 - Introduction
- 1:43 - App Schemas and the plan
- 3:44 - Build the CalendarEntity
- 8:00 - Build the AttendeeEntity
- 10:30 - Build the EventEntity
- 14:34 - Open events with OpenIntent
- 15:30 - Onscreen awareness
- 17:18 - Create events with Siri
- 19:24 - Update events
- 21:30 - Custom snippet views
- 22:30 - Delete events
- 23:35 - Next steps
リソース
- Integrating your calendar app with Apple Intelligence
- Donating your app’s data and actions to the system
- Donations and discovery
- Making app entities available in Spotlight
- Making actions and content discoverable by Apple Intelligence
- Providing contextual cues to Apple Intelligence and Siri
- Apple Intelligence and Siri AI
- Calendar
- App schema domains
関連ビデオ
WWDC26
-
このビデオを検索
Swift Intelligence Frameworksチームの エンジニア Justinです。 このCode Alongへようこそ。 このビデオでは、アプリを Siriに対応させる手順を紹介します。 iPhone上でSiriと会話を始め、 こう尋ねるとします: 「ピクニックには誰が来る?」 Siriはイベントと参加者を検索し ゲストリストを表示します。
いつも遅刻する友人が含まれていると気づき こう言います: 「正午に変更して… やっぱり午前11時30分に。」
Siriが詳細の確認を求めてきたので こう答えます: 「いいね、ありがとう。」
Siriが変更を加えて カスタムビューを表示します。
次に友人に連絡が必要です: 「ピクニックに来る全員にテキストを送って 絵文字で変更を知らせて。」
メッセージを確認した後、こう言います: 「送信して。」
あっという間に Siriがメッセージを送信します。 その後、イベントのメモに リマインダーがあったことを思い出します。 ピクニックに大切なものを 持参するようにとのこと。 そこでこう尋ねます: 「ピクニックに何を 持って行くんだったっけ?」 Siriがイベントを検索し、 チョコレートケーキを持参するという メモを見つけます。
準備時間がどのくらいあるか気になり こう聞きます: 「そこまで車でどのくらいかかる?」
Siriがイベントの場所を調べ 所要時間の見積もりを伝えます。
Siriは会話だけで 日常をスムーズにしてくれます。 それが今日のミッションです。
既存のアプリを Siriに対応させます。 SiriはAppleのパーソナル インテリジェンスシステム Apple Intelligenceで動いています。 デベロッパはApp Intentフレームワークを通じて アプリをApple Intelligenceに統合します。 App Intentフレームワークを使って アプリのコンテンツやアクションを Siri内で利用できるようにします。 その他のシステム機能でも同様です。 関連ビデオ「Build intelligent Siri experiences with App Schemas」では フレームワークの背景にある概念や Apple IntelligenceとSiriがアプリの コンテンツやアクションと連携する仕組みを 解説しています。 App Intentが初めての方には 「Get to know App Intents」で コアの基礎を学べます。 インテント、エンティティ、クエリなど Siriやショートカットなどの システム機能との連携方法も紹介しています。 CometCalというサンプルプロジェクトを 作成してきました。 コスミックなテイストを加えた SwiftUIカレンダーアプリです。 ソースコードはApple Developerサイトから ダウンロードできます。 ぜひ一緒に進めてください。 カレンダーアプリの基本機能を備え 今日のイベント表示や 閲覧・編集 新規作成
複数カレンダーの管理にも対応しています。
今はスクリーンからしか 操作できませんが… それも変わります! このビデオではCometCalを更新して アプリのコンテンツを理解し 質問に答えられるようSiriを対応させます。 イベントの更新などのアクションも可能にし Siriをさらに便利にします。 最初のステップは、アプリのコンテンツを Siriに理解させることです。 今はSiriはCometCal内で カレンダーや イベントが何を意味するか 把握していません。 そこでApp Schemasの出番です。 App Schemaはアプリのコンテンツを Siriが既に理解できる形で 表現します。 エンティティの構造、アクションのパラメータ そして出力を定義します。 トレーニングフレーズや 自然言語処理は不要です。 App SchemaはApp Schemaドメインに 整理されています。
カレンダードメインはスケジュール管理に 関わるすべてをカバーします: イベント、カレンダー、参加者 そしてそれらに対するアクション。 基礎が整ったので、Xcodeに飛び込んで カウントダウンを始めましょう!
いざ出発! CometCalのデータ層には CalendarModelが既にあります。 これはカレンダー用のSwiftDataモデルで 個人カレンダーと仕事カレンダーの 違いを表します。 App Schemaを使ってこれを表す アプリエンティティを作成します。 これでSiriはアプリ内の カレンダーを理解できます。 CalendarEntityという新しいSwiftファイルを作成し AppIntentsをインポートします。
次に、エディタでcalendar_と入力します。 Xcodeはカレンダードメインの全スキーマを オートコンプリートで提案します。 カレンダーエンティティが目的なので calendar_calendarを選択します。
スニペットで構造が入力されます: @AppEntityマクロ、プロパティ、 DisplayRepresentationとクエリのスタブ。 これがスキーマ化エンティティで Siriが推論できる型です。 いくつか入力が必要です。 まずidの型をデータモデルに合わせて UUIDに設定します。
テキストだけでなく 意味でもマッチングできるよう IndexedEntityプロトコルに 準拠します。 IndexedEntityへの準拠により Spotlightインデックスを使って エンティティを提供できます。 セマンティック理解の恩恵を 受けられます。 エンティティが提供されると Siriは名前で解決でき プロパティやコンテキストによっても カスタムプロパティクエリ不要で対応します。 作業を進めるため、変換する方法を 追加しておきました。 データモデルとエンティティ間の変換です。 CalendarEntityのイニシャライザは CalendarModelからマップして エンティティに必要な情報を取り出します。 CalendarModelの .entityコンビニエンスプロパティは イニシャライザを使って CalendarEntityを生成します。 クエリなどで2つの間を変換する際に すぐ使います。
次に、クエリ内のCalendarManagerに @Dependencyプロパティを追加します。 これはCometCalのデータ層で SwiftData操作をすべて処理します。 @Dependencyプロパティラッパーは App Intentが共有リソースを インテントやクエリに注入する仕組みです。 新しいインスタンスを作る代わりに 一度登録した同じオブジェクトを提供します。 右側に示したとおりです。
CalendarManagerは mainアクターに分離されているため クエリ構造体にも @MainActorを付与します。 EntityQueryプロトコルで 必要なメソッドを実装します。 CalendarManager依存関係を使って IDでカレンダーを取得します。 EntityQueryはシステムが エンティティのIDを 既に知っているケースをカバーします。 ただし、後でイベントを作成する際に システムはどのカレンダーが 利用可能かを知る必要があります。 Siriが選択肢として 提示できるようにするためです。 そのためにEnumerableEntityQueryに 準拠して すべてのカレンダーを返す allEntitiesメソッドを追加します。
DisplayRepresentationには タイトルをカレンダーのタイトルに設定し 画像をカレンダーのシステム イメージに設定します。 SiriとSpotlightはエンティティを 表示する際にこれを使用します。 これで1つ目のエンティティの 準備がほぼ整いました。 見落としやすいことが もう1つあります。 IndexedEntityはインデックスされる コンテンツの形状を定義しますが エンティティはまだ提供する必要があります。 そのためにCalendarManagerファイルを 開きます。 カレンダーなどのインデックス化エンティティが 変更されるたびに インデックスを更新する必要があります。 そのためCSSearchableIndexの インスタンスを用意しています。 CalendarManagerの イニシャライザで初期化され CometCal固有の名前を使います。 createCalendarメソッド内で 新しいカレンダーを返す直前に indexAppEntitiesを呼び出して エンティティを提供します。 先ほどのsearchableIndex インスタンスを使います。
同様に、updateCalendarメソッドでも 更新されたカレンダーエンティティを インデックスします。
deleteCalendarメソッドでは deleteAppEntitiesを呼び出して インデックスからエンティティを削除します。 エンティティのidと型を渡します。
エンジンを起動して 試してみましょう… CometCalを開いて「Lunar Orbit Log」という 新しいカレンダーを作成します。
次に下にスワイプして 「Lunar Orbit Log」を検索します…
カレンダーアイコンとタイトルと共に 表示されました。 CalendarEntityが機能しました。次の 2つのエンティティも同じパターンに従いますが それぞれ新しい要素が 加わります。
AppIntentsがインポート済みの AttendeeEntityという新しいファイルです。 前と同じパターンで… calendar_attendeeと入力して スニペットを選択します。 共通部分は同じです… それらはカメラ外で接続済みなので 高速に進められます。 ここで一時停止して完成した ソースコードを確認してください。 CalendarEntityとは異なり、 AttendeeEntityは IndexedEntityではなく TransientAppEntityプロトコルに準拠します。 これは意図的なものです。 トランジエントAppエンティティは 一時的なエンティティを表します。 一意の識別子は不要で クエリも想定されていません。 これがここでは適切です。 CometCalでは参加者は 特定イベントへの参加を表します。 人物そのものではありません。 同じ人が複数のイベントに 参加できますが 参加ごとに個別にインデックスすると Spotlightで重複した 結果が生じます。 参加者は常にそれを保持する イベントを通じてアクセスされるため 独立した検索パスは 不要です。 TransientAppEntityはそれを明示します… クエリの記述も インデックスの管理も不要です。 参加者にはスキーマで 必須とされるプロパティがあります。 この参加がオプションかどうかを 示すbooleanプロパティなどです。
新しい項目として IntentPerson型があります… 人物を表すシステム標準の 方法です。 名前と連絡先情報を持ちます。 これはアプリ間でデータを 共有する際に便利です。 参加者のメールアドレスをメールアプリに 渡してメッセージを作成するなど。 スキーマには 2つの@AppEnum型も含まれます。 スキーマが取り得るケースの セットを定義します。 アプリは該当するケースを採用します。 これらもスキーマ化されているため コードスニペットで素早く作成します。 ステータスにはcalendar_attendeeStatus スニペットを使います。 スニペットにはスキーマが サポートするケースがすべて含まれます。 CometCalのモデルはそのまま対応しているため 変更は不要ですが、アプリが 別の用語を使っている場合は 既存のモデルをスキーマのケースに マッピングするだけです。 Siriが形状を認識できます。 同様に、参加者タイプには calendar_attendeeTypeを使います。 スキーマは参加者の種類を説明する ケースを少なくとも1つ必要とします。 CometCalの参加者はすべて 人物なのでpersonケースを追加します。
statusとtypeに それぞれの型を入力します。
これでAttendeeEntityの 作業が完了しました。
2つのエンティティが完成しました。 残り1つです。 カレンダーと参加者エンティティは 次のエンティティと連携します… それら全体を引き寄せる 重力の中心… EventEntityです。
システムの検索インデックスは イベントエンティティで真価を発揮します。 「クルーランチはいつ?」と 聞かれたとき Siriはタイトルを検索します。 「酸素について言及している イベントは?」と聞かれたとき メモのコンテンツを検索します。 自分のデータについて質問でき Siriが直接答えます。 calendar_eventスニペットが 適用済みのEventEntityです。 CalendarEntityと同様に、EventEntityも IndexedEntityプロトコルに準拠し CalendarManagerにインデックス処理を含めて セマンティックインデックスを活用します。 内容は多いですが スキーマは幅広い プロパティをカバーします。 でも安心してください。前のエンティティと 同じパターンが適用されます。 主な違いはパラメータの 数と種類です。 このミッションを スケジュール通りに進めるため 共通部分はカメラ外で 接続済みです。 一時停止してソースコードを 確認してください。 スキーマはどのプロパティが必須で どれがオプションかを定義します。 titleやstartDateなどの必須項目は 簡単に接続できます。 アプリが使用しない オプションのプロパティ travelTimeやvirtualLocationなどは 未設定のままでかまいません。 スキーマにはないがデータモデルに存在する プロパティ isFavoriteなどはエンティティに 追加することもできます。 このエンティティが興味深いのは 先ほど構築した 他のエンティティとの組み合わせ方です。 このイベントが属するカレンダーは CalendarEntityです…
参加者は AttendeeEntityの配列です。
SiriはApp Schemaで これらの関係を理解します。
recurrenceプロパティも 簡単に触れておく価値があります。 繰り返されるイベントを 表すのに使えます。 毎週のワークアウトや 重要な毎年の記念日など。 FoundationのCalendar.RecurrenceRule型を 使用します。 CometCalのシンプルな 频度enumと相互変換します。 daily、weekly、monthly、yearlyなどの ケースに対応しています。
スキーマの一部として イベントの場所とアラームに ユニオン値もあります。 ユニオン値とは、複数の 異なる型のいずれかを持てるプロパティです。 例えば場所はGeoToolboxフレームワークの PlaceDescriptorか Stringのどちらかを取れます。 これらもコードスニペットで 実装できます。
このようにします。 アラームはDurationか Dateのどちらかです。
これらの型に プロパティを割り当てます。
参加者と同様に スキーマ化されたenumがあります。 EventEntityStatusなどです。 イベント関連の両enumは スニペットで完成しているため 追加して接続します。
最後に、statusプロパティを 新しいstatus型に割り当てます。 これでコンテンツ層は 完全に準備完了です。
これが離陸できるか 確かめましょう! 左側はMeteor Shower Watch Partyの 詳細ビューです。 時間、場所、メモが 画面に表示されています… Siriと流星について 会話している最中に パーティーのことを 突然思い出したとします。 会話を中断してCometCalを開いて 詳細を確認する代わりに こう尋ねるだけです… 「Meteor Shower Partyは もうすぐある?」
「そこの天気は?」
テキスト入力に 切り替えることもできます: 「ピーク観測時間はいつ?」
結果をタップして CometCalに移動することもできます。
Siriはアプリのコンテンツを使って すべての質問に答えます。 カスタムの自然言語処理は不要です… エンティティとスキーマだけで十分。 気づいたかもしれませんが Siriとの会話からイベントをタップすると CometCalが開きます。 ただしメイン画面に 移動するだけです。
期待どおりにイベントには ナビゲートされません。 Siriはまだアプリ内の特定の イベントを開く方法を知りません。 少し回り道をして このエクスペリエンスをさらに改善します。 これを実現するには OpenEventIntentを使います。 system.openスキーマに準拠する 小さなインテントです。 EventEntityをターゲットとして受け取り NavigationManagerにそのイベントへの ナビゲーションを指示します。 SpotlightやSiriでイベント結果をタップするか Siriにイベントを開くよう求めると システムがこれを呼び出します。
以上です! イベントをタップすると… 今度はCometCalが 詳細ビューに直接移動します。 Meteor Shower Watch Partyが 表示されます。 OpenIntentがギャップを埋めます。 Siriはアプリのコンテンツを これまで以上に理解できるので 何でもSiriに聞けます。 3つの構造体とコードスニペットを いくつか入力するだけですね。
Siriとの会話をさらに自然に 感じさせることが もう1つできます。 特定のイベントが 画面に表示されているとき こんなことを言いたくなるかもしれません: 「このイベントの参加者にメールして」 とイベント名を言わずに。 それが画面認識で… 2つのビューモディファイアだけです。 CometCalのCalendarListViewで 全イベントを一覧表示する場所に リストに.appEntityIdentifier モディファイアを追加します。 各イベントエンティティの EntityIdentifierを渡します。 これでリストがエンティティと接続され リストを閲覧しているとき システムはどのイベントが 画面に表示されているかを把握します。 イベント詳細ビューでは 1つのイベント詳細が表示されているとき EntityIdentifierを含む .userActivityモディファイアを追加します。 これにより特定のイベントが 前面にあることをシステムに通知し Siriはそのイベントを 表示中のものに正確に解決できます。
以上です! 有効になる内容を見てみましょう。 SiriがオンスクリーンのコンテンツとEventEntityを 開けるようになったので Siriに自然な方法でイベントを 開くよう頼みます: 「Hey Siri、3番目のイベントを開いて。」
Meteor Shower Watch Partyの詳細ビューを 表示している今 タイトルを全部言わずに このイベントを参照してみます… 「Hey Siri、このイベントの参加者にメールして チョコレートとマシュマロを 誰かに持参するよう頼んで。」
Siriは画面上のイベントの 理解を活かして 参加者を見つけてメールに 引き渡せます。
本当に… 2つのモディファイアだけで… 画面上のコンテンツとアプリの内容を つなぐのに十分です。 Siriはコンテンツについて 話せるようになりました。 真に離陸するために Siriにアクションの能力を与えます。 ここでもApp Schemaが道を開きます。 ここからが本当に 面白くなります。 イベントの作成から始めます。
エンティティと同様に インテントもコードスニペットを使います。 calendar_createEventスニペットを見つけて 選択します。 @AppIntentマクロでインテントを スキャフォールドします。 スキーマ、スキーマが必要とするすべての パラメータ、そしてperformスタブ。 titleからnoteまでのパラメータは スキーマから来ており、インテントの performロジックで使用できます。 まず型を入力します。 次に@Dependencyを追加します。 performメソッドで使う CalendarManagerのためです。 performメソッドでは @MainActorを付けて 戻り値の型をEventEntityに設定します。
一般的なパターンは シンプルです: インテントのパラメータをデータ層が 理解できる形に解決し アクションを実行して 結果をエンティティとして返す。 カレンダーイベントの作成では パラメータを解決します。 ユニオン値から場所を 抽出するなど
繰り返しが指定されていれば変換します。 calendarManagerのcreateEventメソッドに すべて渡して 結果をEventEntityとして返します。
これは驚くべきことです。 App Schemaに準拠しているため Siriが重労働を担います。 言語の解釈、確認の要求、 詳細の確認… 自然な会話を Siriと楽しめます。 早速試してみましょう… 新しいイベントを作成したいとします。 でも宇宙遊泳の最中で iPhoneが手の届かないところに浮いています。 掴む代わりに Siriに頼みます… 「Hey Siri、Lunar Orbit Logに 新しいイベントを作成して。」
「Zero Gravity Yogaという名前で 6月15日の午前8時に。」
Siriはタイトル、日付、時刻を 解決できます。 完了するとイベントが カレンダーに追加されます。
数行のコードで アプリがSiriと連携します。 App Schemaの力です。 イベントをSiriで作成できるようになったので 勢いに乗ってイベントの 更新に進みます。
これがUpdateEventIntentです。 calendar_updateEventスニペットを使って 既に入力済みです。 createインテントと 構造は似ていますが 主な違いはほとんどの パラメータがオプションなことです。 1つか2つしか変更しない 場合があるためです。 eventパラメータはSiriが解決し それ以外はすべてオプションです。 performロジックは同じパターンで: 各パラメータを提供されていれば解決し CalendarManagerのupdateEventメソッドに すべて渡して 更新されたイベントを返します。 createインテントより コードが多いかもしれませんが 完全に新しいことは 何もありません。
ただし、1つ重要な 微妙な点があります。 updateインテントのオプション パラメータで注意が必要です。 例えば、recurrenceがnilの場合 「変更しない」のか「削除する」のか どちらを意味するのでしょうか? 単純なnilチェックでは どちらのケースか判断できません。 performメソッドのrecurrenceロジックを 見てみると @AppIntentマクロは各プロパティを IntentParameterでラップして valueStateを公開します。 これで判断できます。 実際の値を持つ.setは 新しい値が提供されたことを意味します。 nil値を持つ.setは 明示的にクリアされたことを意味します。 .unsetはパラメータが リクエストに含まれていないことを意味します。 このパターンは オプションパラメータに適用されます。 値のクリアが 意味のあるアクションである場合です。 updateインテントの接続が完了したので いくつかのコマンドを 試してみましょう: 「Hey Siri、これを 夜10時に変更して。」
「はい、いいですよ。」
「これを毎週繰り返しに変えて Deep Spaceカレンダーに移動して。」
「了解です。」
「やっぱり、このイベントを 繰り返さないで。」
詳細ビューに すべての変更が反映されます。 数行のコードと App Schemaだけです。
更新は機能しますが Siriはデフォルトの結果カードを表示します。 CometCalには もっと… 雰囲気が必要です。
デフォルトではSiriは表示表現から 結果カードを構築します。 スニペットビューでそれをカスタムの SwiftUIビューに置き換えられます。 EventEntityを受け取り詳細を 壮大に表示するSwiftUIビューを用意しました。 詳細をスター風に表示します。 かなり創造性を発揮できますが… シンプルで軽量に 保つことも忘れずに。 これをすべて接続するために UpdateEventIntentを開きます。
performメソッドの戻り値の型に ShowsSnippetViewを追加します。 return文でEventSnippetViewを 渡します。 同じアプローチは結果を返す 他のインテントでも機能します。 createインテントなど。
「Hey Siri、クルーランチを 1時間後にずらして。」
新しいスニペットが表示されました! コズミックなグラデーションのアクセント ダークブルーの背景 更新されたイベント詳細と スターアイコン… アプリの個性が Siriの中で輝いています。 updateインテントのカバーは完了です。
最後に接続するアクションは削除で 3つの中で最もシンプルです。 DeleteEventIntentです。 非常にシンプルです… イベントと繰り返しイベント用の オプションのspanだけです。 performロジックはイベントを見つけて 削除します。 Siriは削除前に自動的に 確認ダイアログを表示します。
イジェクションシーケンスをテストします: 「Siri、そのパーティーを削除して。」
「はい、削除して。」
「あと、6月9日に あるイベントを削除して。」
「あ…やっぱりいいです。」
Siriはイベントを削除する前に 確認を求め 複数のイベントが一致する場合は 明確化も行います。 3つのインテント。 Siriで完全なイベント管理が可能に。 ミッション完了! CometCalは画面操作から 完全な音声操作に変わりました。
このビデオで多くを構築しました。 自分のアプリをSiriに対応させるための 次のステップを紹介します。 CometCalサンプルプロジェクトをダウンロードして 完全な実装を調べてください。 App Intentのドキュメントを参照して 利用可能なすべてのApp Schemaと ドメインを確認してください。 自動テストについては、このビデオで CometCalのテストの書き方を学べます。 新しいAppIntentsTestingフレームワークを 使用します。 「Explore advanced App Intents features for Siri and Apple Intelligence」を 視聴すると、アプリとSiriの連携を 洗練させる方法をさらに深く学べます。 このビデオでは扱いきれなかった内容です。 アプリを最前線へと 飛び立たせる準備が整いました。 ご視聴ありがとうございました!
-
-
- 0:00 - Introduction
Justin Kang previews the goal: take an existing app and make it available to Siri. A picnic scenario shows Siri searching events, updating times with confirmation, texting attendees, and answering questions, all through conversation.
- 1:43 - App Schemas and the plan
Apps integrate with Apple Intelligence through App Intents, and App Schemas describe content and actions in terms Siri already understands, no training phrases or NLP. Schemas are organized into domains (here, the calendar domain). Introduces the CometCal sample app and the two goals: understand content, and perform actions.
- 3:44 - Build the CalendarEntity
Create a schematized @AppEntity from the calendar_calendar snippet, set the id to UUID, conform to IndexedEntity, wire a @Dependency and @MainActor query (EnumerableEntityQuery with allEntities()), set a display representation, and donate to Spotlight via indexAppEntities and deleteAppEntities.
- 8:00 - Build the AttendeeEntity
Built from calendar_attendee, but conforming to TransientAppEntity instead of IndexedEntity, attendees are accessed only through their event, so they need no identifier, query, or index. Introduces the IntentPerson type and two schematized @AppEnums (calendar_attendeeStatus, calendar_attendeeType).
- 10:30 - Build the EventEntity
The central IndexedEntity (from calendar_event), where the semantic index shines for title and note-content questions. Composes the CalendarEntity and [AttendeeEntity], handles recurrence (Calendar.RecurrenceRule), union values for location and alarms, and event status/span enums.
- 14:34 - Open events with OpenIntent
A small OpenEventIntent conforming to the system.open schema takes an EventEntity and tells the NavigationManager to navigate to it, so tapping an event in Spotlight or Siri opens straight to its detail view.
- 15:30 - Onscreen awareness
Two view modifiers connect the screen to entities: .appEntityIdentifier on the event list and .userActivity (with an EntityIdentifier) on the detail view, letting Siri resolve "this event" or "that third event" without naming the title.
- 17:18 - Create events with Siri
Build CreateEventIntent from calendar_createEvent: fill in parameter types, add a @MainActor @Dependency, and in perform() resolve the schema parameters (location union value, recurrence) into the data layer and return an EventEntity. Siri handles language, clarification, and confirmation.
- 19:24 - Update events
UpdateEventIntent (calendar_updateEvent) mostly mirrors create, but parameters are optional. The key subtlety: an IntentParameter's valueState distinguishes .set with a value (change it), .set with nil (explicitly clear it), and .unset (not part of the request).
- 21:30 - Custom snippet views
Replace Siri's default result card by adding ShowsSnippetView to the intent's return type and returning a custom SwiftUI EventSnippetView, bringing the app's visual personality (cosmic gradient, star icon) into Siri.
- 22:30 - Delete events
DeleteEventIntent is the simplest, just the event plus an optional span for recurring events, and Siri automatically handles confirmation and disambiguation before deleting.
- 23:35 - Next steps
Download the CometCal sample, browse the App Intents documentation for all schemas and domains, write tests with AppIntentsTesting, and watch "Explore advanced App Intents features for Siri and Apple Intelligence."