App Intents ve Swift pro iOS 26: Průvodce Siri, Apple Intelligence a Shortcuts (2026)

Kompletní návod, jak zapojit App Intents do SwiftUI aplikace pro iOS 26. Ukazuje App Schemas, interaktivní snippety, integraci s Apple Intelligence, testování v Xcode 16.5 a nejčastější chyby při přechodu z SiriKit.

App Intents iOS 26: Průvodce Siri (2026)

Aktualizováno: 19. července 2026

App Intents je framework, který ve Swiftu popisuje, co vaše aplikace umí a jaký obsah spravuje, aby ji Siri, Apple Intelligence, Spotlight, Shortcuts a widgety mohly volat i bez otevření aplikace. V iOS 26 se framework posunul o generaci dál, přibyly App Schemas, interaktivní snippety, integrace do Visual Intelligence a asynchronní @DeferredProperty. Průvodce ukazuje, jak App Intents zapojit do reálné SwiftUI aplikace bez zbytečného boilerplate, tak, jak jsem si to sám odzkoušel na dvou produkčních aplikacích během letního migračního maratonu.

  • App Intents nahradily SiriKit už v iOS 16; v iOS 26 se stávají hlavním vstupním bodem pro Apple Intelligence a nové systémové zážitky.
  • Nový koncept App Schemas mapuje vaše intenty na typy, kterým Siri rozumí trénovaně – bez definice frází a bez nutnosti přepisovat kód, když se Siri zlepší.
  • Interaktivní snippety otevírají malé okno vaší aplikace přímo v Siri, Spotlightu a Visual Intelligence – bez plného přechodu.
  • @DeferredProperty umožňuje asynchronně dopočítávat drahé vlastnosti entit, takže velké seznamy zůstávají svižné.
  • Nový App Intents Testing framework ověří integraci se Siri, Shortcuts a Spotlightem bez UI automatizace.
  • Kvalitní AppEntity je základ všeho – bez ní App Intents nefungují, jen vypadají, že fungují.

Co jsou App Intents a proč je řešit v iOS 26

App Intents je deklarativní Swift API, kterým aplikaci vystrčíte ven ze sandboxu obrazovky. Popíšete typem, co umí udělat (AppIntent), co spravuje za obsah (AppEntity) a jaké dotazy nad tím obsahem má systém dovolit (EntityQuery, IntentValueQuery). Zbytek (hlasové zpracování v Siri, indexování ve Spotlightu, generování widgetu, kroky v Shortcuts, chování s Apple Intelligence) řeší systém.

V iOS 26 se hra změnila proto, že Siri teď umí tři věci současně: přistupuje k vašim entitám („Kdy je moje další schůzka?“), spouští vaše intenty přes přirozený jazyk („Pošli poslední report Marii.“) a rozumí kontextu na obrazovce, když view označíte anotací entity. Aplikace, která žádné App Intents nemá, se v tomto novém režimu stává pro OS de facto neviditelnou. Není to nadsázka. Spotlight sémantický index, personální kontext a Visual Intelligence si vyžádají obsah právě přes tento framework.

Zajímavá historická poznámka: kdo psal na iPhonu Objective-C ještě před SiriKit, pamatuje si INIntent a genericky vygenerované třídy z .intentdefinition souborů. App Intents je jejich ergonomický pravnuk. Místo XML a kódogenerace píšete čistý Swift s makry a property wrappery. Volitelná složitost se drží stranou, dokud ji sami nechcete.

Rozdíl mezi SiriKit a App Intents

SiriKit z roku 2016 fungoval na doménách. Aplikace musela zapadnout do jedné z předdefinovaných kategorií (zprávy, jízdy, platby) a používat vygenerované třídy. App Intents jsou doménově otevřené: definujete si vlastní typy a systém si s nimi poradí, mimo jiné právě proto, že jazykový model za Siri se učí schémata, ne konkrétní věty.

VlastnostSiriKit (INIntent)App Intents (iOS 16+, iOS 26 rozšíření)
Definice intentuXML v .intentdefinitionSwift typ s makrem @AppIntent
Podporované doményUzavřený seznam Apple doménVlastní intenty + App Schemas pro běžné kategorie
Vazba na fráziNutné hlídat vzoryPřirozený jazyk, systém vyhodnocuje
Spotlight indexaceNe přímoAno přes AppEntity a IndexedEntity
Widgety a Live ActivitiesNeAno, přes stejné intenty
Apple IntelligenceNepodporovánoNativní integrace, hlavní vstupní bod
Testovací pipelineUI simulace v XcodeApp Intents Testing framework (Xcode 16.5+)

Krátká rada z praxe: pokud stále udržujete SiriKit intenty pro zpětnou kompatibilitu do iOS 15, nechte je běžet, ale nové funkce už do nich necpěte. App Intent lze paralelně přidat a systém rozumí, že jde o modernější variantu. V iOS 26 přechod už není if you want, je to when.

Jak přidat App Intent do SwiftUI aplikace

Než začneme, malá poznámka o architektuře. App Intents běží v odlehčeném procesu, který systém spouští i mimo hlavní aplikaci. To znamená, že intent nemá přímý přístup k UI stavu. Přistupujete k datům přes sdílený úložný model – App Group, SwiftData store, případně přes URL scheme, kterou intent po dokončení dispatchne aplikaci. Podrobněji jsem to popsal v článku o SwiftData od základů po pokročilé techniky, tady se zaměřím na samotný intent.

Uvažujme aplikaci pro poznámky. Definice intentu, který vytvoří poznámku:

import AppIntents

struct CreateNoteIntent: AppIntent {
    static var title: LocalizedStringResource = "Vytvořit poznámku"
    static var description = IntentDescription(
        "Uloží novou poznámku do vaší schránky.",
        categoryName: "Poznámky"
    )
    static var openAppWhenRun: Bool = false

    @Parameter(title: "Obsah")
    var body: String

    @Parameter(title: "Štítek", default: "Rychlá")
    var tag: String

    func perform() async throws -> some ProvidesDialog & ReturnsValue<NoteEntity> {
        let note = try await NoteStore.shared.append(body: body, tag: tag)
        return .result(
            value: NoteEntity(note: note),
            dialog: "Poznámka uložena pod štítkem \(tag)."
        )
    }
}

Pár věcí, které stojí za zdůraznění. openAppWhenRun nechte na false, kdykoli intent zvládnete bez UI, aby uživatel z Shortcutu neviděl bliknutí aplikace. Návratový typ some ProvidesDialog & ReturnsValue<NoteEntity> je klíčový: Siri promluví „Poznámka uložena…“ a zároveň nabídne uloženou entitu jako výstup, který jde použít v dalším kroku Shortcuts. Je to jedno z drobných, ale zásadních API rozhodnutí, hodnota a dialog, ne jedno bez druhého. (Na tomhle jsem shořel v beta 1, protože jsem si myslel, že ReturnsValue vypne mluvenou odpověď. Nevypne.)

Aby Siri intent uměla, přidejte navíc AppShortcut:

struct NotesShortcuts: AppShortcutsProvider {
    static var appShortcuts: [AppShortcut] {
        AppShortcut(
            intent: CreateNoteIntent(),
            phrases: [
                "Vytvoř poznámku v \(.applicationName)",
                "Přidej poznámku v \(.applicationName)"
            ],
            shortTitle: "Nová poznámka",
            systemImageName: "note.text.badge.plus"
        )
    }
}

Fráze jsou nápověda pro Siri, ne kompletní gramatika. V iOS 26 systém odvozuje varianty automaticky, takže dvě rozumné fráze bohatě stačí. Neplýtvejte tam všechny synonymní věty, které vás napadnou.

AppEntity: modelujte obsah, ne obrazovky

Bez slušně navržené AppEntity nefunguje ani Spotlight, ani Apple Intelligence, ani Shortcuts řetězení. Entity popisuje co aplikace obsahuje, jak se to identifikuje a které vlastnosti jsou pro uživatele smysluplné:

struct NoteEntity: AppEntity, IndexedEntity {
    let id: UUID

    @Property(title: "Nadpis")
    var title: String

    @Property(title: "Vytvořeno")
    var createdAt: Date

    @DeferredProperty(title: "Náhled")
    var preview: String {
        get async throws {
            try await NoteStore.shared.previewSnippet(for: id)
        }
    }

    static var typeDisplayRepresentation: TypeDisplayRepresentation = "Poznámka"

    var displayRepresentation: DisplayRepresentation {
        DisplayRepresentation(title: "\(title)", subtitle: "\(createdAt.formatted(date: .abbreviated, time: .shortened))")
    }

    static var defaultQuery = NoteQuery()
}

@DeferredProperty je novinka z iOS 26 a je fakt šikovná: náhled poznámky se dopočítá až ve chvíli, kdy jej Siri nebo Spotlight potřebuje zobrazit. Do té doby se vlastnost neserializuje ani nesynchronizuje. U velkých seznamů to dělá výrazný rozdíl. Dřív jste museli buď načíst všechno, nebo obsah oddělit do jiné entity, což bylo nešikovné.

Query typ pak systému říká, jak entity hledat:

struct NoteQuery: EntityQuery {
    func entities(for identifiers: [UUID]) async throws -> [NoteEntity] {
        try await NoteStore.shared.notes(with: identifiers).map(NoteEntity.init)
    }

    func suggestedEntities() async throws -> [NoteEntity] {
        try await NoteStore.shared.recent(limit: 20).map(NoteEntity.init)
    }

    func entities(matching string: String) async throws -> [NoteEntity] {
        try await NoteStore.shared.search(query: string).map(NoteEntity.init)
    }
}

Tři metody stačí, aby Spotlight uměl full-textově hledat, Shortcuts nabízel „nedávné poznámky“ a Siri uměla resolvovat větu „Otevři poznámku Nákup…“ Jednodušší už to skoro nemůže být.

App Schemas: nová generace integrace se Siri

Nejzajímavější přírůstek z WWDC26 sessionu 240 „Build intelligent Siri experiences with App Schemas“ je koncept schémat. Schéma je systémem předdefinovaný tvar intentu nebo entity, například TaskManagement.CreateTask, PhotoEditing.ApplyFilter nebo Communication.SendMessage. Když vaše aplikace deklaruje, že její intent implementuje takové schéma, Siri o něm ví bez toho, abyste definovali fráze:

@AppIntent(schema: .taskManagement.createTask)
struct CreateNoteIntent: AppIntent {
    static var title: LocalizedStringResource = "Vytvořit poznámku"

    @Parameter(title: "Obsah") var body: String
    @Parameter(title: "Termín") var dueDate: Date?

    func perform() async throws -> some IntentResult {
        try await NoteStore.shared.append(body: body, due: dueDate)
        return .result()
    }
}

Kouzelné je, že jak se Siri jazykově zlepší, vaše schéma z toho těží zdarma. Žádný redeploy, žádná úprava kódu. Prakticky to znamená, že aplikace, která používá schémata, drží krok s OS i po vydání. Trochu to připomíná adopci Symbol frameworku, jakmile se zapojíte, další updaty vás už jen zvedají.

Ne každá aplikace samozřejmě zapadne do standardní kategorie. Pro doménově specifické akce zůstávají klasické AppIntenty bez schématu. V praxi doporučuji projít oficiální dokumentaci App Intents a schémata použít všude, kde dávají sémanticky smysl, zbytek nechat vlastní.

Interaktivní snippety a Visual Intelligence

Druhá velká novinka jsou interaktivní snippety. Až dosud snippet znamenal statické zobrazení výsledku intentu v Siri. V iOS 26 může být snippet malé SwiftUI okno s tlačítky, ovládacími prvky a dokonce s vlastními intenty:

struct NoteSnippetView: View {
    let entity: NoteEntity

    var body: some View {
        VStack(alignment: .leading, spacing: 8) {
            Text(entity.title).font(.headline)
            Text(entity.createdAt, style: .date)
                .font(.caption).foregroundStyle(.secondary)
            HStack {
                Button(intent: PinNoteIntent(note: entity)) {
                    Label("Připnout", systemImage: "pin")
                }
                Button(intent: ShareNoteIntent(note: entity)) {
                    Label("Sdílet", systemImage: "square.and.arrow.up")
                }
            }
        }
        .padding()
    }
}

Snippet se zobrazí ve Spotlightu, v Siri odpovědi i ve Visual Intelligence, kam uživatel promítne obrázek. To znamená, že pokud rozpoznávaný obraz odpovídá entitě z vaší aplikace, snippet se objeví přímo v systémovém UI, bez otevření aplikace.

Pro Visual Intelligence potřebujete druhý typ query, IntentValueQuery, který systému říká, jak z obrázku odvodit entitu:

struct NoteVisualQuery: IntentValueQuery {
    func values(for input: SemanticImage) async throws -> [NoteEntity] {
        let tags = try await input.detectedTextTokens
        return try await NoteStore.shared.matching(tokens: tags).map(NoteEntity.init)
    }
}

Nový je i pojem View annotation. Ve své SwiftUI hierarchii označíte view, které reprezentuje entitu, a Siri s Apple Intelligence si toho všimne pro dotazy typu „Vysvětli tenhle text“ nebo „Přidej tenhle produkt do košíku“:

NoteRow(note: note)
    .appEntity(NoteEntity(note: note))

Jedna řádka, systém zbytek zvládne. Anotace se dobře snoubí s Foundation Models on-device AI, protože jakmile Apple Intelligence rozpozná entitu, můžete ji ihned poslat do modelu jako kontext.

Donace intentů a Focus Filters

Donace je způsob, jak aplikace systému říká: „Tohle uživatel právě dělá, možná to bude chtít zopakovat.“ V App Intents se donuje přes IntentDonationManager:

try await IntentDonationManager.shared.donate(
    intent: CreateNoteIntent(body: text, tag: "Denní")
)

Systém z donace odvodí, kdy a jak intent uživateli nabídnout: v Shortcutech, ve Spotlightu jako návrh, ve widgetu Suggestions. Zásadní pravidlo je nepřehánět. Donuje se skutečně dokončená akce, ne každý tap. Přehnané donace systém začne ignorovat, a bohužel to nikde nehlásí, takže se to zjistí, až když návrhy prostě přestanou chodit.

Focus Filters umožňují, aby uživatel při určitém režimu (Práce, Cesta) automaticky odfiltroval kontext aplikace, například jen pracovní poznámky. Konfigurují se přes SetFocusFilterIntent a řeší, které AppEntity jsou v daném režimu viditelné. Krátký vzor:

struct NotesFocusFilterIntent: SetFocusFilterIntent {
    static var title: LocalizedStringResource = "Filtr poznámek"

    @Parameter(title: "Zobrazit štítek")
    var tag: String?

    func perform() async throws -> some IntentResult {
        NoteStore.shared.activeFilter = tag
        return .result()
    }
}

Focus filtry jsou z pohledu autora API elegantní: jeden intent, žádné delegáty, žádný UNUserNotificationCenter boilerplate. To je věc, kterou v Objective-C SiriKit člověk marně hledal.

Jak testovat App Intents v Xcode 16.5+

Až do letošního jara byl test App Intents smutná záležitost, buď XCUITest s hlasovými pokyny v simulátoru, nebo ruční klikání. Xcode 16.5 přinesl App Intents Testing framework, který spustí intent přes stejné systémové cesty jako Siri, ale bez UI:

import AppIntentsTesting
import Testing

@Suite struct CreateNoteIntentTests {
    @Test func createsAndReturnsEntity() async throws {
        let intent = CreateNoteIntent()
        intent.body = "Koupit chleba"
        intent.tag = "Nákup"

        let result = try await intent.performForTesting()

        #expect(result.value?.title == "Koupit chleba")
    }
}

Spouští se v Swift Testing runneru, takže syntaxe je moderní #expect. Framework navíc simuluje resolving – pokud v intentu chybí povinný parametr, dostanete stejnou chybu, jakou by dostal Shortcuts uživatel. To dřív šlo zjistit jen empiricky, což bolelo.

Testovat můžete i entity queries a snippet views. Snippet snapshot test v podstatě otestuje vzhled tak, jak jej uvidí Siri, což je v uvozovkách end-to-end test bez toho, abyste museli sáhnout na simulátor. Podrobnější rozbor WWDC26 sessionu 343 „Explore advanced App Intents features“ stojí za shlédnutí – pokrývá i debugging donace a snapshot snippetů.

Nejčastější chyby a jak se jim vyhnout

Za pět let, co App Intents sleduji a čtu cizí bug reporty, se opakují stejné vzorce. Zde jsou ty, které stojí za pozornost, obzvláště při přechodu z iOS 25 na iOS 26:

  • Chybějící DisplayRepresentation u entity. Bez ní Siri vypíše prázdný řádek, Spotlight nezobrazí náhled, Shortcuts ukáže ID. Vždy dodejte alespoň title a subtitle.
  • Špatně zvolený openAppWhenRun. Když aplikace bliká při každém intentu, uživatel to vzdá. Nechte false, kdykoli akci zvládnete v pozadí. Aplikaci otevírejte jen tehdy, když opravdu chcete UI.
  • Synchronní IO ve perform(). Intent běží v odlehčeném procesu s omezeným časem. Pomalý dotaz do sítě znamená timeout. Použijte async, případně přesuňte drahou práci do @DeferredProperty.
  • Zbytečně mnoho AppShortcut frází. Šest variant jednoho příkazu Siri zmate a zvýší šanci na kolizi s jinou aplikací. Držte se dvou.
  • Testování jen v Shortcuts. Shortcuts nezaznamená problém s Apple Intelligence resolvingem. Používejte také performForTesting().
  • Ignorovaná Swift 6 souběžnost. App Intent typy jsou často předány mezi izolacemi. Buďte striktní se Sendable, jinak vás Xcode 16.5 zastaví ještě před buildem.

Poslední rada s pohledem staršího vývojáře. App Intents jsou v iOS 26 už osmým rokem de facto API pro chytré integrace a rozhraní se stabilizuje. Investice do slušně navržené entity a jednoho tucta intentů se vrací dlouhodobě – widgety, Shortcuts, Siri, Apple Intelligence i budoucí systémové UI si berou to samé. Kdo si udělá pořádek jednou, může další roky přidávat funkce s minimem lepení.

Časté dotazy

Fungují App Intents i bez Apple Intelligence?

Ano. App Intents primárně nejsou o Apple Intelligence – jsou o systémových integracích: Shortcuts, Siri, Spotlight, widgety, Focus Filters. Apple Intelligence je jen jeden z jejich konzumentů. Aplikace, která běží na iPadu bez Apple Intelligence, má z App Intents pořád velkou hodnotu.

Jaký je minimální požadavek na verzi iOS pro App Intents?

Základní framework je od iOS 16. Novinky jako App Schemas, interaktivní snippety, @DeferredProperty a integrace do Visual Intelligence vyžadují iOS 26. Xcode 16.5 nebo novější je pro plnou podporu potřeba.

Můžu App Intents použít v macOS a watchOS aplikaci?

Ano. App Intents jsou multiplatformní – běží na iOS, iPadOS, macOS, watchOS, tvOS i visionOS. Některé nadstavby (Visual Intelligence, snippety ve Spotlightu) jsou vázané na konkrétní platformy, ale samotné intenty a entity jsou přenositelné bez úprav.

Jak sdílet stav mezi App Intent extension a hlavní aplikací?

Standardně přes App Group container – SwiftData store, sdílený UserDefaults(suiteName:) nebo CoreData store v App Group. Přímo sáhnout na runtime stav aplikace nejde, protože intent běží v jiném procesu. Pro synchronní notifikaci hlavní aplikace použijte NSDarwinNotification.

Rozumí App Intents českým hlasovým příkazům?

Ano, ale se stejnými limity jako celý Siri v češtině. V iOS 26 Siri v češtině rozpozná parametrické fráze („Vytvoř poznámku v Poznámkách“), ale pokročilé konverzační scénáře fungují nejlépe s Apple Intelligence, která je zatím dostupná primárně v angličtině. Definujte fráze lokalizované přes LocalizedStringResource, aby se s rozšířením podpory nemuselo do kódu sahat.

Lukas Müller
O Autorovi Lukas Müller

iOS developer and Swift author since the Objective-C days. Spends his evenings on side projects and his mornings on SwiftUI internals.