← Wszystkie wpisy

App Schemas: udostępnij swoją aplikację dla Siri

Na WWDC 2026 inżynier Apple wziął napisaną w SwiftUI aplikację kalendarza, która reagowała wyłącznie na dotknięcia, i sprawił, że Siri przeszukiwała jej wydarzenia, odpowiadała na pytania o nie po nazwie i treści notatek, tworzyła je i aktualizowała głosem oraz renderowała niestandardową kartę wyniku — a wszystko to, pisząc trzy struktury i uzupełniając garstkę fragmentów kodu.1 Mechanizmem stojącym za tą zmianą jest App Schemas: sposób opisania treści i działań aplikacji w pojęciach, które Siri już rozumie, bez fraz treningowych i bez przetwarzania języka naturalnego po stronie programisty.1 Sesja ma formę code-along zbudowanego wokół przykładowego projektu o nazwie CometCal, a lekcja kryjąca się pod kosmicznym motywem ma charakter strukturalny. Nie uczysz Siri swojego słownictwa. Deklarujesz swoje dane i działania względem kształtu, który Siri już zna, a reszta wynika sama.

Ten artykuł omawia trzy filary niosące ten rezultat: model schemat-domena, semantyczne przekazanie (donation) do Spotlight przez IndexedEntity oraz świadomość ekranu wraz z rozróżnieniem valueState, które czyni bezpiecznymi aktualizacje sterowane głosem. Wszystko, co poniżej, pochodzi wprost z sesji. Temat różni się od wykonywania w tle w App Intents, które obejmuje uruchamianie pracy bez otwierania interfejsu; tutaj nacisk pada na to, jak Siri wnioskuje na podstawie treści i działa na niej.

TL;DR

  • App Schemas opisują encje aplikacji, parametry jej działań oraz wyniki w pojęciach, które Siri już rozumie, uporządkowane w App Schema Domains; domena kalendarza obejmuje wydarzenia, kalendarze, uczestników i działania na nich, bez fraz treningowych i bez NLP po stronie programisty.1
  • Encje schematyzowane pochodzą z fragmentów kodu Xcode: wpisujesz prefiks domeny taki jak calendar_ i wybierasz fragment (na przykład calendar_calendar), co tworzy szkielet encji z jej makrem, właściwościami, reprezentacją wyświetlania i zarysami zapytań.1
  • Doprowadzenie encji do zgodności z IndexedEntity i przekazanie jej do CSSearchableIndex przez indexAppEntities (oraz usunięcie jej przez deleteAppEntities) pozwala Siri rozpoznać ją po nazwie, po właściwości lub po kontekście, bez niestandardowego zapytania o właściwość.1
  • Dwa view modifiers, .appEntityIdentifier na liście i .userActivity na widoku szczegółów (każdy niosący EntityIdentifier), dają Siri świadomość ekranu, dzięki czemu prośba taka jak „wyślij e-mail do osób z tego wydarzenia” zostaje rozwiązana bez nazywania wydarzenia.1
  • Intenty aktualizacji udostępniają IntentParameter.valueState, gdzie .set z wartością, .set z nil oraz .unset rozróżniają nową wartość, jawne wyczyszczenie i nieobecny parametr, dzięki czemu edycje sterowane przez Siri pozostają jednoznaczne.1

Czym tak naprawdę są App Schemas (sesja 344)

Watch on Apple Developer ↗

Justin z zespołu Swift Intelligence Frameworks wyjaśnia App Schemas przed otwarciem Xcode, począwszy od 3:12.

Siri dociera do aplikacji przez framework App Intents, a wnioskowanie nadbudowane na tym napędza Apple Intelligence.1 Problem wyjściowy w CometCal jest prosty: „W tej chwili Siri nie ma pojęcia, co wewnątrz CometCal oznacza kalendarz albo wydarzenie.”1 App Schemas zamykają tę lukę. Jak ujmuje to sesja, „opisują treść i działania mojej aplikacji w pojęciach, które Siri już potrafi zrozumieć. Definiują strukturę moich encji, parametry moich działań oraz wyniki. Bez fraz treningowych, bez przetwarzania języka naturalnego po mojej stronie.”1

Jednostką porządkującą jest App Schema Domain. Domena kalendarza „obejmuje wszystko, co związane z planowaniem: wydarzenia, kalendarze, uczestników i działania, które na nich operują.”1 Ponieważ kształty są predefiniowane, katalogowaniem zajmuje się edytor. Inżynier tworzy plik CalendarEntity, importuje AppIntents, wpisuje calendar_, a „Xcode podpowiada każdy schemat z domeny Calendar, wprost w autouzupełnianiu.”1 Wybranie calendar_calendar wypełnia strukturę: makro encji, właściwości, reprezentację wyświetlania i zarysy zapytań, tworząc coś, co sesja nazywa „encją schematyzowaną, typem, na którym Siri może wnioskować.”1

Konwencja nazewnictwa zasługuje na uważną uwagę. Nazwy fragmentów schematu pojawiają się w edytorze jako identyfikatory pisane małymi literami z prefiksem podkreślenia (calendar_calendar, calendar_attendee, calendar_event, calendar_createEvent, calendar_updateEvent, a także fragmenty enum, takie jak calendar_attendeeStatus i calendar_attendeeType), i tak też oddaje je transkrypcja mówiona. Typy Swift, których szkielet tworzą (makro @AppEntity, DisplayRepresentation, zgodności z protokołami zapytań), stosują się do zwykłej pisowni wielkimi i małymi literami w Swift. Sprawdź dokładną pisownię i wielkość liter każdego symbolu w dokumentacji App Intents firmy Apple oraz w możliwym do pobrania przykładowym projekcie CometCal, zanim zaczniesz na nich kompilować, ponieważ mówiony code-along nie jest precyzyjnym źródłem dla wielkości liter.

Korzyścią z modelu schematów jest szeroki zasięg przy bardzo małej ilości kodu. Sesja przedstawia całą warstwę treści jako „trzy struktury i uzupełnienie kilku fragmentów kodu.”1 CometCal buduje trzy encje o rosnącym bogactwie: kalendarz, uczestnika oraz wydarzenie, które łączy dwie pozostałe. Wydarzenie „komponuje się z innymi encjami zbudowanymi wcześniej”: jego kalendarz to CalendarEntity, a jego uczestnicy to tablica AttendeeEntity, i „Siri rozumie te zależności dzięki App Schemas.”1 Schemat decyduje również o tym, co jest wymagane, a co opcjonalne. Elementy niezbędne, takie jak tytuł czy data rozpoczęcia, podpinają się bezpośrednio, opcjonalne właściwości schematu, których aplikacja nie używa (sesja wymienia czas podróży i lokalizację wirtualną), mogą pozostać nieustawione, a właściwość, która istnieje w modelu danych, lecz nie w schemacie, taka jak isFavorite, i tak może zostać dodana do encji.1

Na wydarzeniu pojawiają się jeszcze dwa mechanizmy schematu. Wartości union pozwalają, by jedna właściwość przechowywała jeden z kilku typów: lokalizacja może być „albo PlaceDescriptor z frameworka GeoToolbox, albo String”, a alarm może być albo Duration, albo Date.1 Właściwość powtarzalności korzysta z Calendar.RecurrenceRule z Foundation i konwertuje w obie strony z własnym enumem częstotliwości CometCal dla przypadków dziennego, tygodniowego, miesięcznego i rocznego.1 Schematyzowane enumy (sesja wskazuje enum statusu wydarzenia, który nazywa EventEntityStatus, oraz powyższe enumy uczestnika) przybywają z fragmentu kompletne, a aplikacja przyjmuje przypadki, które mają zastosowanie; jeśli aplikacja używa innej terminologii, odwzorowujesz istniejący model na przypadki schematu, „aby Siri mogła rozpoznać kształt.”1

Semantyczne przekazanie przez IndexedEntity

Schemat daje Siri słownictwo. Przekazanie daje Siri rzeczywiste dane, na których ma wnioskować. To dwa odrębne kroki, a sesja wyraźnie mówi, że łatwo przeoczyć drugi: „IndexedEntity definiuje kształt mojej zaindeksowanej treści, ale encje wciąż muszą zostać przekazane.”1

Doprowadzenie encji do zgodności z protokołem IndexedEntity to właśnie to, co umożliwia dopasowanie po znaczeniu, a nie wyłącznie po tekście.1 Powodem jest indeks wyszukiwania. Zgodność „pozwala mojej aplikacji przekazywać encje za pomocą indeksu Spotlight, by uzyskać korzyści ze zrozumienia semantycznego”, a gdy encja zostanie przekazana, „Siri może ją rozpoznać po nazwie, po właściwości lub po kontekście, bez konieczności niestandardowego zapytania o właściwość.”1 To ostatnie zdanie jest całym sednem. Nie piszesz żadnego dedykowanego dopasowywacza dla „lunchu załogi” ani „wydarzeń wspominających tlen”. Siri przeszukuje wprost przekazane tytuły i treść notatek oraz „odpowiada na każde pytanie, korzystając z treści aplikacji. Bez potrzeby niestandardowego języka naturalnego… wystarczą encje i schematy.”1

Przekazanie przebiega przez CSSearchableIndex. CometCal przechowuje instancję CSSearchableIndex, utworzoną w inicjalizatorze swojego CalendarManager pod nazwą unikalną dla aplikacji.1 Reguła, którą formułuje sesja, brzmi: „za każdym razem, gdy zmieniają się kalendarze, a w zasadzie jakakolwiek zaindeksowana encja, indeks musi zostać zaktualizowany.”1 Dlatego warstwa danych przekazuje przy zapisie: ścieżka tworzenia wywołuje indexAppEntities z indeksem wyszukiwania przed zwróceniem, ścieżka aktualizacji ponownie indeksuje zmienioną encję, a ścieżka usuwania wywołuje deleteAppEntities, „przekazując id i typ encji.”1 Po podłączeniu encji kalendarza inżynier tworzy kalendarz o nazwie „Lunar Orbit Log”, przesuwa palcem, by wyszukać, i znajduje go z ikoną oraz tytułem — dowód, że przekazanie zadziałało.1

Nie każda encja powinna być indeksowana, a uczestnik to kontrprzykład, który uczy tej reguły. AttendeeEntity jest zgodne z TransientAppEntity, a nie z IndexedEntity — to „tymczasowa encja, która nie wymaga unikalnego identyfikatora i nie jest przeznaczona do odpytywania.”1 U podstaw tego leży dyscyplina modelowania: w CometCal uczestnik reprezentuje „udział osoby w konkretnym wydarzeniu, a nie samą osobę”, ta sama osoba może uczestniczyć w wielu wydarzeniach, a „indeksowanie każdego uczestnictwa osobno tworzyłoby zduplikowane wyniki w Spotlight.”1 Ponieważ do uczestników zawsze dociera się przez ich wydarzenie, nie ma niezależnej ścieżki wyszukiwania do utrzymania, a TransientAppEntity „czyni to jawnym… żadnego zapytania do napisania, żadnego indeksu do utrzymywania.”1 Uczestnik wprowadza również IntentPerson, „systemowy standardowy sposób reprezentowania osoby z nazwą i informacjami kontaktowymi”, przydatny do przekazania adresu e-mail uczestnika do Mail w celu utworzenia wiadomości.1

Zaindeksowane encje wciąż potrzebują swojego oprzewodowania zapytań. Zapytanie przechowuje warstwę danych za pomocą property wrappera @Dependency, „sposobu, w jaki App Intents wstrzykuje współdzielone zasoby do intentów i zapytań”, dzięki czemu zapytanie korzysta z jedynego zarejestrowanego CalendarManager, a nie ze świeżej instancji, a samo zapytanie jest oznaczone jako main-actor, ponieważ manager nim jest.1 Wymagana metoda EntityQuery pobiera po ID w przypadkach, gdy system już je zna, a zgodność z EnumerableEntityQuery poprzez metodę allEntities pozwala systemowi później wylistować dostępne kalendarze, gdy Siri musi zaoferować je jako opcje podczas tworzenia wydarzenia.1 DisplayRepresentation (tytuł plus systemowy obraz kalendarza) mówi Siri i Spotlight, jak renderować encję.1

Warto nazwać pewien szew nawigacyjny, ponieważ samo przekazanie sprawia, że użytkownik ląduje na głównym ekranie aplikacji. OpenEventIntent, który jest zgodny ze schematem system.open, przyjmuje EventEntity jako cel i każe warstwie nawigacji do niego przejść, zamyka tę lukę: system wywołuje go „za każdym razem, gdy ktoś dotknie wyniku wydarzenia w Spotlight lub Siri albo poprosi Siri o jego otwarcie”, dzięki czemu dotknięty wynik otwiera się prosto do widoku szczegółów wydarzenia.1

Świadomość ekranu i rozróżnienie valueState

Pierwsze dwa filary pozwalają Siri znajdować treść po nazwie. Trzeci pozwala Siri wykorzystać to, co już znajduje się przed użytkownikiem, a następnie działać na tym bez dwuznaczności.

Świadomość ekranu kosztuje „zaledwie dwa view modifiers.”1 W widoku listy .appEntityIdentifier dołącza się do listy, „przekazując EntityIdentifier dla każdej z encji wydarzeń”, co „łączy listę z jej encjami, tak że gdy ktoś przegląda listę, system wie, które wydarzenia są na ekranie.”1 W widoku szczegółów .userActivity niesie EntityIdentifier dla pojedynczego wydarzenia w centrum uwagi, mówiąc systemowi, „że to jedno konkretne wydarzenie jest na pierwszym planie, aby Siri mogła rozpoznać to wydarzenie dokładnie jako to, które jest oglądane.”1 Gdy oba są na miejscu, użytkownik na widoku szczegółów wydarzenia może powiedzieć „wyślij e-mail do osób z tego wydarzenia i poproś kogoś o przyniesienie czekolady oraz pianek marshmallow”, a Siri wykorzystuje swoje rozumienie wydarzenia na ekranie, by znaleźć uczestników i przekazać ich do Mail, bez potrzeby tytułu.1

Działanie na treści to ten sam wzorzec co jej odczytywanie, uruchomiony wstecz. Intenty również pochodzą z fragmentów. Fragment calendar_createEvent tworzy szkielet intentu z jego makrem, schematem, parametrami, których wymaga schemat, oraz zarysem metody perform.1 Logika perform ma trzyetapowy kształt, który sesja formułuje wprost: „rozwiąż parametry intentu na coś, co warstwa danych rozumie, wykonaj działanie i zwróć wynik jako encję.”1 W przypadku tworzenia oznacza to wydobycie lokalizacji z jej wartości union, konwersję powtarzalności, jeśli została podana, wywołanie metody tworzenia managera i zwrócenie EventEntity.1 Ponieważ intent jest zgodny ze schematem, „Siri może zająć się całą ciężką pracą: interpretacją języka, prośbą o doprecyzowanie i potwierdzaniem szczegółów”, tak że programista nigdy nie pisze tej rozmowy.1

Aktualizacje wydobywają na wierzch subtelność, która czyni edycje sterowane głosem godnymi zaufania. Większość parametrów calendar_updateEvent jest opcjonalna, ponieważ użytkownik zwykle zmienia jedną lub dwie rzeczy, a „parametr wydarzenia jest tym, co rozwiązuje Siri; cała reszta jest opcjonalna.”1 Zwykłe sprawdzenie nil nie potrafi odpowiedzieć na prawdziwe pytanie. Jak ujmuje to sesja: „gdy powtarzalność jest nil, czy oznacza to »nie zmieniaj jej«, czy »usuń ją«? Zwykłe sprawdzenie nil nie mówi mi, z którym przypadkiem mam do czynienia.”1 Odpowiedzią jest IntentParameter.valueState, udostępniany dlatego, że makro intentu opakowuje każdą właściwość w IntentParameter. Trzy stany niosą odrębne znaczenie: „.set z rzeczywistą wartością oznacza, że podano nową wartość. .set z wartością nil oznacza, że została jawnie wyczyszczona. .unset oznacza, że parametr nie jest częścią żądania.”1 Rozróżnienie „stosuje się do każdego opcjonalnego parametru, w którym wyczyszczenie wartości jest znaczącym działaniem”, dlatego „nie powtarzaj tego wydarzenia” niezawodnie czyści powtarzalność, zamiast pozostawiać ją nietkniętą.1

Dwa wykończeniowe akcenty dopełniają warstwę działań. Niestandardowa karta wyniku zastępuje domyślną kartę reprezentacji wyświetlania Siri: dodanie ShowsSnippetView do typu zwracanego metody perform i przekazanie przygotowanego widoku SwiftUI (ten z sesji przyjmuje EventEntity) renderuje wewnątrz Siri własny styl aplikacji — podejście, które „działa dla każdego innego intentu zwracającego wynik.”1 A DeleteEventIntent, „najprostszy z trzech”, przyjmuje jedynie wydarzenie i opcjonalny span dla wydarzeń powtarzalnych; Siri „automatycznie obsługuje okno potwierdzenia, zanim cokolwiek zostanie usunięte” i ujednoznacznia, gdy pasuje więcej niż jedno wydarzenie.1

Najważniejsze wnioski

Dla programistów iOS wdrażających App Intents:

  • Sięgaj najpierw po schemat. Wpisz prefiks domeny taki jak calendar_ w Xcode i pozwól autouzupełnianiu wylistować dostępne fragmenty; fragment tworzy szkielet makra, właściwości, reprezentacji wyświetlania i zarysów zapytań, dzięki czemu uzupełniasz typy i mapowanie, zamiast wymyślać strukturę.1
  • Dla każdej encji zdecyduj, czy zasługuje na indeks. Doprowadź trwałą, odpytywalną treść do zgodności z IndexedEntity i przekaż ją; użyj TransientAppEntity dla rekordów typu uczestnictwo (uczestnik w CometCal), do których zawsze dociera się przez rodzica i które po zaindeksowaniu jedynie zaśmiecałyby Spotlight.1
  • Sprawdź dokładną pisownię i wielkość liter symboli w dokumentacji App Intents firmy Apple oraz w przykładzie CometCal przed kompilacją, ponieważ nazwy z code-along pochodzą z transkrypcji mówionej.

Dla zespołów projektujących przepływy głosowe i Apple Intelligence:

  • Traktuj przekazanie jako obowiązek ścieżki zapisu. Wywołuj indexAppEntities przy tworzeniu i aktualizacji oraz deleteAppEntities przy usuwaniu, kluczując po id i typie encji, aby indeks Siri nigdy nie rozjechał się z danymi.1
  • Dodaj świadomość ekranu wcześnie: .appEntityIdentifier na listach i .userActivity na widokach szczegółów (każdy niosący EntityIdentifier) pozwalają użytkownikom mówić „to wydarzenie” zamiast podawać jego tytuł.1
  • Obsługuj valueState jawnie w intentach aktualizacji. Rozgałęziaj na .set-z-wartością, .set-z-nil i .unset, aby jawne wyczyszczenie nigdy nie zostało odczytane jako „pozostaw bez zmian.”1

FAQ

Czym są App Schemas w App Intents?

App Schemas opisują treść i działania aplikacji w pojęciach, które Siri już rozumie: definiują strukturę encji aplikacji, parametry jej działań oraz wyniki, bez fraz treningowych i bez przetwarzania języka naturalnego po stronie programisty. Są uporządkowane w App Schema Domains; domena kalendarza obejmuje wydarzenia, kalendarze, uczestników i działania na nich. W Xcode przyjmujesz schemat, wpisując prefiks domeny taki jak calendar_ i wybierając fragment kodu, na przykład calendar_calendar, który tworzy szkielet encji.1

Jak Siri rozpoznaje treść mojej aplikacji po nazwie lub kontekście?

Doprowadź encję do zgodności z protokołem IndexedEntity i przekaż ją do CSSearchableIndex (indeksu Spotlight), wywołując indexAppEntities przy tworzeniu i aktualizacji oraz deleteAppEntities z id i typem encji przy usuwaniu. Przekazanie daje Siri „zrozumienie semantyczne”, pozwalając jej rozpoznać encję po nazwie, po właściwości lub po kontekście bez niestandardowego zapytania o właściwość, w tym przeszukiwać treść notatek dla pytań takich jak „które wydarzenia wspominają tlen?”1

Kiedy powinienem użyć TransientAppEntity zamiast IndexedEntity?

Użyj TransientAppEntity dla tymczasowej encji, która nie potrzebuje unikalnego identyfikatora i nie jest przeznaczona do odpytywania. Uczestnik w CometCal pasuje, ponieważ uczestnik reprezentuje udział osoby w konkretnym wydarzeniu, a nie samą osobę; ta sama osoba uczestniczy w wielu wydarzeniach, a indeksowanie każdego uczestnictwa osobno tworzyłoby zduplikowane wyniki w Spotlight. Ponieważ do uczestników dociera się wyłącznie przez ich wydarzenie, nie ma niezależnej ścieżki wyszukiwania, więc encja tymczasowa nie potrzebuje ani zapytania, ani indeksu.1

Czym jest valueState i dlaczego ma znaczenie dla intentów aktualizacji?

W intencie aktualizacji makro App Intents opakowuje każdą właściwość w IntentParameter, który udostępnia valueState. Rozróżnia on trzy przypadki, których sprawdzenie nil nie potrafi: .set z wartością oznacza nową wartość, .set z nil oznacza, że wartość została jawnie wyczyszczona, a .unset oznacza, że parametr nie był częścią żądania. Rozróżnienie pozwala edycjom sterowanym przez Siri wyczyścić właściwość (na przykład „nie powtarzaj tego wydarzenia”) bez mylenia tego z „pozostaw bez zmian.”1

Jak dać Siri świadomość ekranu mojej aplikacji?

Dodaj dwa view modifiers. Umieść .appEntityIdentifier na widoku listy, przekazując EntityIdentifier dla każdej encji wydarzenia, aby system wiedział, które wydarzenia są na ekranie podczas przeglądania. Umieść .userActivity z EntityIdentifier na widoku szczegółów, aby system wiedział, że jedno konkretne wydarzenie jest w centrum uwagi. Razem pozwalają użytkownikowi powiedzieć „wyślij e-mail do osób z tego wydarzenia”, a Siri rozpoznaje „to wydarzenie” dokładnie jako to, które jest oglądane.1


Ten artykuł należy do klastra o frameworkach inteligencji firmy Apple. Po framework, na którym opierają się App Schemas, zacznij od App Intents: nowe API Apple do twojej aplikacji. Po uruchamianie pracy intentu bez otwierania interfejsu, co jest odrębną kwestią od omawianego tutaj wnioskowania na treści, przeczytaj wykonywanie w tle w App Intents. Po szerszą opowieść o przekazaniu do Spotlight stojącą za rozpoznawaniem semantycznym zobacz AI na urządzeniu i indeksowanie mediów w Spotlight. Pełnym centrum serii jest seria Apple Ecosystem.

Bibliografia


  1. Apple, WWDC 2026 session 344, Code-along: Make your app available to Siri. Źródło dla App Schemas i App Schema Domains (domena kalendarza; bez fraz treningowych, bez NLP); encje schematyzowane przez fragmenty Xcode (calendar_calendar, calendar_attendee, calendar_event, calendar_createEvent, calendar_updateEvent, calendar_attendeeStatus, calendar_attendeeType); IndexedEntity i przekazanie do Spotlight przez CSSearchableIndex za pomocą indexAppEntities / deleteAppEntities; rozpoznawanie po nazwie, właściwości lub kontekście; TransientAppEntity i uzasadnienie modelowania uczestnika; IntentPerson; wartości union (PlaceDescriptor z frameworka GeoToolbox, String; alarmy Duration lub Date) i Calendar.RecurrenceRule; wrapper @Dependency, EntityQuery, EnumerableEntityQuery oraz DisplayRepresentation; OpenEventIntent typu system.open; świadomość ekranu przez .appEntityIdentifier i .userActivity niosące EntityIdentifier; IntentParameter.valueState (.set/.unset); niestandardowa karta wyniku ShowsSnippetView; potwierdzenie i ujednoznacznianie w DeleteEventIntent; oraz framework AppIntentsTesting przywołany dla testów automatycznych. 

Powiązane artykuły

App Intents to nowe API Apple do Twojej aplikacji

8 lutego 2026 wdrożyłem App Intent w aplikacji Water. Oto czego Apple Intelligence oczekuje od aplikacji zewnętrznych w …

14 min czytania

MetricKit przebudowany: telemetria świadoma stanu w iOS 27

MetricKit zostaje przebudowany w iOS 27: asynchroniczne strumienie metryk i diagnostyki, raporty Codable oraz framework …

10 min czytania

Loop Engineering: Loops Win Where Verification Is Cheap

Loop engineering, checked against Boris Cherny's full transcripts: every loop he names has cheap verification. That cons…

19 min czytania