View in English

  • Global Nav Open Menu Global Nav Close Menu
  • Apple Developer
Search
Cancel
  • Apple Developer
  • News
  • Discover
  • Design
  • Develop
  • Distribute
  • Support
  • Account
Only search within “”

Quick Links

5 Quick Links

Vídeos

Abrir menu Fechar menu
  • Coleções
  • Tópicos
  • Todos os vídeos
  • Sobre

Mais vídeos

  • Sobre
  • Resumo
  • Transcrição
  • Código
  • Explore os novos avanços do framework App Intents

    Explore todos os aprimoramentos disponíveis nas versões deste ano do framework App Intents. Saiba mais sobre melhorias que facilitam o dia a dia dos desenvolvedores, como propriedades adiadas (deferred properties), novos recursos como trechos interativos de App Intents, anotações de visualização de entidades, integração com Inteligência Visual e muito mais. Mostraremos como o App Intents está mais expressivo e ainda mais simples e fácil de adotar. Você também vai conhecer os novos clientes do App Intents, como o Spotlight e a Inteligência Visual, e aprender a criar app intents que funcionam perfeitamente nesses contextos.

    Capítulos

    • 0:00 - Introdução
    • 0:55 - Snippets interativos
    • 8:15 - Novas integrações do sistemas
    • 15:01 - Melhorias na experiência do usuário
    • 21:02 - APIs de conveniência

    Recursos

    • Accelerating app interactions with App Intents
    • Adopting App Intents to support system experiences
    • App intent domains
    • App Intents
    • App Shortcuts
    • Building a workout app for iPhone and iPad
    • Creating your first app intent
    • Integrating actions with Siri and Apple Intelligence
    • Making actions and content discoverable and widely available
    • PurchaseIntent
      • Vídeo HD
      • Vídeo SD

    Vídeos relacionados

    WWDC25

    • Conheça o App Intents
    • Crie snippets interativos
    • Desenvolva para o app Atalhos e o Spotlight com o App Intents

    WWDC24

    • Bring your app to Siri
    • Bring your app’s core features to users with App Intents
    • Design App Intents for system experiences
    • What’s new in App Intents
  • Buscar neste vídeo...

    Olá! Meu nome é Jeff. Sou engineer na equipe App Intents. Hoje, vamos explorar novos avanços em App Intents.

    Isso permite que o app integre seus recursos nos dispositivos das pessoas, incluindo áreas como Atalhos, Spotlight e Inteligência Visual.

    Se você não conhece o framework, confira a sessão "Conhecer o App Intents" primeiro. Você pode voltar a qualquer momento. Vamos abordar diversos tópicos hoje, incluindo novidades em snippets interativos, maneiras adicionais de o app usar App Intents em todo o sistema, mais recursos para aprimorar a experiência de usuário do app e várias APIs de conveniência disponíveis para melhorar a experiência do desenvolvedor. Vamos começar com os snippets interativos.

    Eles permitem ao app exibir visualizações personalizadas com App Intents, para pedir confirmação ou exibir um resultado. Agora você pode dar vida a esses snippets com interatividade. Por exemplo, você pode criar um snippet de jardinagem para ligar os irrigadores quando o solo estiver muito seco. Ou configurar um pedido antes de enviá-lo ao restaurante. Ou fazer integração com outros recursos do sistema, como Atividades ao Vivo, para acompanhar um jogo logo após conferir o placar.

    Vou demonstrar um snippet interativo com nosso app de exemplo. Depois vamos ver a implementação.

    O app TravelTracking contém inúmeros pontos de referência no mundo. Vou tocar no controle que executa uma App Intent para encontrar o mais próximo.

    A Intent localizará e mostrará um snippet exibindo o ponto de referência com um coração ao lado do título. Sou de Toronto. Muito perto de Niagara Falls. Vou tocar no botão do coração para adicionar o local aos favoritos.

    O snippet é atualizado imediatamente para mostrar o novo status. Isso é criado com o uso do novo protocolo Snippet Intent. As Intents renderizam visualizações de acordo com seus parâmetros e o estado do app. Você pode usá-las para exibir resultados após uma ação ou solicitar confirmação. Vamos explorar os snippets de resultados. Qualquer Intent no app pode retornar uma Snippet Intent com valores de parâmetro como parte do resultado. Isso é usado pelo sistema sempre que ele precisa atualizar o snippet. Quando isso acontecer, o sistema preencherá os parâmetros na Snippet Intent com os valores especificados. Para entidades do app, elas serão buscadas nas consultas.

    Depois o sistema executa o método perform da Snippet Intent. Lá, a Intent pode acessar seus parâmetros e o estado do app para renderizar a visualização, retornando-a como parte do resultado. A visualização pode associar botões ou controles com App Intents do app.

    No exemplo, o botão de coração executa Update Favorites Intent, e o botão para localizar ingressos executa Find Tickets Intent. Você não precisa criar essas Intents apenas para snippets. Você pode reutilizar as existentes sem modificá-las.

    Quando o botão é tocado, o sistema executa a Intent correspondente e aguarda a conclusão. Isso garante a atualização do status de favorito. A terminar, o sistema usará a Snippet Intent com parâmetros retornada anteriormente para disparar outra atualização. Como antes, você preencherá os parâmetros com os valores especificados. Quaisquer entidades do app serão buscadas nas consultas novamente. O sistema executará o método perform, que dá à Snippet Intent a chance de renderizar uma visualização atualizada. O ícone de coração agora é preenchido. As alterações na visualização serão animadas de acordo com as APIs contentTransition da SwiftUI. O ciclo continua até o snippet ser descartado.

    Vamos implementar o retorno de uma Snippet Intent. Vou abrir a Intent existente e adicionar ShowsSnippetIntent ao tipo de retorno. Em seguida, forneço a Snippet Intent usando o novo parâmetro no método result. Isso orienta o sistema a preencher o parâmetro com o ponto de referência fornecido sempre que a Snippet Intent for usada.

    Agora vamos implementar a Snippet Intent. Primeiro, ela precisa estar em conformidade com o protocolo SnippetIntent. Depois, adiciono as variáveis necessárias para a renderização correta. Elas devem ser marcadas como parâmetros para serem preenchidas pelo sistema. E, como é uma App Intent, também tem acesso a AppDependencies. No tipo de retorno do método perform, adicione ShowsSnippetView. No corpo, use métodos para buscar os estados necessários para gerar a visualização e retorne-a usando o parâmetro view em um método result.

    Semelhante às visualizações SwiftUI, sua Snippet Intent será criada e executada muitas vezes em seu ciclo de vida. Garanta que ela não altere o estado do app. O sistema pode até executá-la mais vezes para reagir a mudanças do dispositivo, como ativar o modo escuro. Renderize suas visualizações rapidamente para mantê-las responsivas.

    Como você especifica valores de parâmetro uma vez, só deve usá-los para App Entities, que são sempre consultadas, e valores primitivos que nunca mudam. Todos os outros valores devem ser buscados no método perform.

    Com o snippet criado, vamos ver como a visualização SwiftUI aciona Intents.

    No corpo da visualização, LandmarkView usa o inicializador Button para associar as App Intents correspondentes. Também há APIs semelhantes para controles. Elas foram introduzidas com widgets interativos junto com o modificador contentTransition para personalizar animações.

    Para saber mais, confira a apresentação de Luca, de 2023. Agora vamos implementar o recurso Find Tickets usando um snippet de confirmação. Se eu tocar no botão Find Tickets, ele perguntará quantos ingressos estou buscando. Vou aumentar para quatro, pois meus amigos vêm, e iniciar a busca. Ela mostrará o melhor preço que um snippet de resultado permite encontrar. Vamos analisar passo a passo. Começando com o snippet de resultado, se os botões ou controles acionarem Intents que mostram os próprios snippets, ele substituirá o original. Isso só funciona se o original estiver mostrando um resultado. A Intent de acompanhamento pode mostrar qualquer tipo de snippet. Estamos usando a confirmação de solicitação para mostrar a visualização de configuração. Para isso, basta chamar o método requestConfirmation. Você pode personalizar o nome da ação e fornecer a Snippet Intent que orienta a experiência de confirmação.

    Esse método gera um erro caso o snippet seja cancelado a qualquer momento. Não tente capturá-lo, apenas deixe-o encerrar o método perform.

    Cada interação com a visualização terá o mesmo ciclo de atualização que o snippet de resultado.

    No exemplo, a Snippet Intent sempre mostra o número atualizado de ingressos. Como ela faz isso? Criei o modelo de solicitação de busca como AppEntity, assim o sistema sempre buscará o valor mais recente da consulta ao preencher esse parâmetro. Posso passá-lo para minha visualização e obter automaticamente os valores.

    O sistema não encerrará o app enquanto o snippet estiver visível, por isso você pode manter os estados na memória. Não é necessário armazená-los em um banco de dados.

    Após todas as interações, quando a ação Search é tocada, a execução original de App Intents é retomada.

    Você pode querer que seu snippet seja atualizado no meio de uma tarefa porque há um novo estado.

    Nesse caso, basta chamar o método reload estático na Snippet Intent que deve ser atualizada.

    Confira esta sessão para saber como criar os melhores snippets interativos. Os snippets foram só o começo. Agora vamos ver de que outras formas as App Intents podem ajudar a integrar o app ao sistema. A primeira é a busca de imagens. Esse recurso permite fazer buscas diretamente em uma captura da câmera ou uma captura de tela. Uma novidade no iOS 26 é poder exibir os resultados da busca do seu app. Esta é a captura de tela de um ponto de referência. Vou destacá-la para fazer uma busca de imagens, e o sistema mostrará um painel. Posso selecionar o app TravelTracking para ver os resultados. Quando eu tocar em um resultado, ele abrirá o app na página correspondente.

    Para permitir a busca, implemente uma consulta compatível com o protocolo IntentValueQuery. Ele aceitará o tipo SemanticContentDescriptor como entrada e retornará uma matriz de App Entities. A busca de imagens exibirá as AppEntities usando suas representações de exibição.

    Ao tocar em um resultado, a AppEntity correspondente é enviada à OpenIntent para o app manipulá-la. Essa OpenIntent deve existir para seu app ser exibido.

    Para implementar a consulta, comece com uma struct compatível com o protocolo IntentValueQuery. O método values deve ter SemanticContentDescriptor como entrada. Ele contém os pixels da área selecionada. Use APIs do Video Toolbox ou CoreImage para convertê-lo em um tipo conhecido, como CGImage.

    Após executar a busca, retorne uma matriz das entidades correspondentes. E implemente uma Intent compatível com o protocolo OpenIntent para permitir o toque no resultado. O parâmetro target deve ter o mesmo tipo de entidade que os resultados. OpenIntents não só oferecem suporte à busca de imagens. Também podem ser chamadas em locais como o Spotlight, facilitando a navegação dos usuários até uma entidade no app.

    As pessoas terão a melhor experiência se encontrarem o que procuram rapidamente. Portanto, retorne algumas páginas de resultados para a correspondência perfeita poder aparecer na interface do sistema. Use seus servidores para consultar um conjunto de dados maior. Porém, a busca não deve demorar muito. Ou parecerá que não está respondendo. Por fim, permita que continuem a experiência de busca no app se não encontrarem o que procuram. Vamos adicionar isso ao TravelTracking.

    Quando não vejo o que quero na lista, posso tocar no botão de mais resultados, que abre meu app e navega até a visualização de busca. Para implementar, use a nova macro AppIntent para especificar o esquema semanticContentSearch. Essa é a nova API que substitui a macro AssistantIntent, pois expandimos os esquemas para recursos fora do assistente, como o visualIntelligence. Adicione a propriedade de conteúdo semântico exigida pelo esquema. A macro a marcará automaticamente como um parâmetro Intent.

    No método perform, processe os metadados da busca e navegue até a visualização de busca. Quero adicionar o recurso que faz o TravelTracking mostrar coleções que contenham os pontos de referência correspondentes. Mas como posso ter uma consulta que retorne uma mistura de LandmarkEntity e CollectionEntity? A resposta é UnionValues. Primeiro, declare um UnionValue com cada caso representando um tipo de entidade que a consulta pode retornar. Depois altere o tipo de resultado para uma matriz deles. Agora posso retornar uma mistura das duas. Não se esqueça de implementar uma OpenIntent para cada tipo de entidade. Para saber mais sobre UnionValues, confira a sessão sobre App Intents apresentada por Kenny em 2024.

    É ótimo que o conteúdo do app possa ser buscado fora dele, mas é possível fazer mais com a Apple Intelligence quando o app está ativo. Vamos falar sobre entidades na tela. O uso de NSUserActivities permite ao app associar entidades ao conteúdo na tela. Assim, as pessoas podem perguntar ao ChatGPT sobre o que está visível no app.

    No app TravelTracking, olhando para Niagara Falls, posso perguntar à Siri se o lugar é próximo ao oceano. A Siri descobrirá que me refiro à visualização na tela e se oferecerá para enviar uma captura ao ChatGPT. Mas a LandmarkEntity aceita PDF, então vou escolher a opção de conteúdo completo. Posso fornecer uma prévia e, em seguida, enviá-la.

    A resposta será exibida. Aprendi que os Grandes Lagos NÃO são um oceano. Para associar uma entidade a uma visualização, vamos adicionar o modificador userActivity a LandmarkDetailView. No fechamento da atualização, associe um identificador de entidade à atividade. Precisamos permitir a conversão de LandmarkEntity em um tipo de dados que o ChatGPT entenda, como um PDF.

    Primeiro, criamos conformidade com o protocolo Transferable e, depois, fornecemos a representação dos dados em PDF. Outros tipos compatíveis incluem texto simples e texto avançado. Confira esta documentação de App Intents para saber mais sobre entidades na tela.

    Aproveitando o gancho sobre como expor o conteúdo do app ao sistema, vou apresentar o Spotlight. Agora que há suporte para executar ações diretamente no Spotlight no Mac, você pode usar App Intents para oferecer a melhor experiência.

    Primeiro, torne as entidades do app compatíveis com IndexedEntity e doe-as ao Spotlight. Isso permite que a busca do Spotlight direcione a experiência de filtragem para seus parâmetros. Para associar propriedades de entidades às chaves do Spotlight, você pode usar o novo parâmetro indexingKey no atributo property. Neste exemplo, forneci a continent uma customIndexingKey. Isso permitirá a busca por pontos de referência asiáticos apenas digitando "Ásia" no campo de texto. Como bônus pela adoção da API, isso permite ao app Atalhos gerar automaticamente ações de localização para suas entidades.

    Segundo, anote o conteúdo na tela com entidades, para elas serem priorizadas nas sugestões quando as visualizações estiverem ativas. Terceiro, implemente PredictableIntent para que o sistema aprenda com o comportamento anterior do usuário e sugira Intents com base em Intents e parâmetros utilizados. Você pode até fornecer descrições personalizadas, dependendo de seus valores.

    Para saber mais sobre esse recurso, confira esta sessão sobre o Atalhos e o Spotlight. Agora que você tem todos esses recursos em seu app, vou mostrar algumas formas de aprimorar a experiência do usuário. Vamos começar com Desfazer. As pessoas são mais propensas a tentar algo diferente se souberem que podem mudar de ideia. Por isso, é importante que possam reverter ações realizadas no app. Com o novo protocolo UndoableIntent, você pode permitir que as pessoas desfaçam App Intents com gestos que já conhecem.

    Aqui estão algumas das minhas coleções no app TravelTracking. Vou usar Digite para a Siri para executar um dos meus atalhos personalizados para excluir a coleção Sweet Deserts. Após a confirmação, ela será removida do app. Se eu mudar de ideia, posso deslizar para a esquerda com três dedos para acionar o undo e restaurar a coleção.

    DeleteCollectionIntent participa da pilha de desfazer em conformidade com o protocolo UndoableIntent. Ele fornece uma propriedade opcional undoManager, que permite registrar as ações de desfazer. Há outras operações disponíveis, como setActionName. Mesmo quando a Intent é executada em uma extensão, o sistema fornece o Undo Manager mais relevante por meio dessa propriedade. Isso garante a sincronização das ações de desfazer na interface e em App Intents, para que sejam desfeitas na ordem correta. Vamos aprimorar essa Intent fornecendo alternativas à exclusão.

    Podemos usar a nova API de múltipla escolha para apresentar várias opções. Executarei a Intent que exclui a coleção novamente. Agora, em vez de apenas me pedir para confirmar a exclusão, aparece a opção de arquivá-la.

    Essa coleção me traz recordações. Acho que vou arquivá-la. No método perform, apresente o snippet de múltipla escolha chamando o método requestChoice e forneça uma matriz de opções usando o parâmetro between. As opções podem ser criadas com títulos personalizados. Especifique também um estilo para dizer ao sistema como renderizá-la.

    Personalize o snippet com uma caixa de diálogo e uma visualização SwiftUI.

    Quando uma opção é selecionada, ela é retornada do método requestChoice, exceto para cancelamento, que gera um erro que encerra o método perform. Você não deve capturar esse erro. Se uma solicitação for cancelada, a Intent deverá parar imediatamente.

    Como acompanhamento, use uma instrução switch para ramificar na opção escolhida. Você pode usar as opções originais criadas como os valores esperados. Vamos explorar mais um ponto de aprimoramento. Os modos compatíveis oferecem às suas Intents maior controle do primeiro plano do app. Isso permite que se comportem de forma diferente dependendo da interação do usuário com o dispositivo. Por exemplo, ao dirigir, quero que as Intents me forneçam informações apenas por voz. Porém, ao olhar para o dispositivo, ele deve me levar diretamente para o app para mostrar mais informações. Com esse recurso, posso implementar uma App Intent que faz as duas coisas. Vou mostrar a você.

    Aqui está a Intent para obter o status da lotação de Niagara Falls.

    Vou desativar a opção Abrir ao Executar. Isso se assemelha a cenários em que o primeiro plano não é possível, como utilizar a Siri usando fones de ouvido. Ao executá-la, aparecerá apenas uma caixa de diálogo, que pode ser lida pela Siri.

    Mas se eu a executar desativando a caixa de diálogo e ativando Abrir ao Executar, acesso diretamente a página do ponto de referência que mostra a ocupação e o clima atual.

    Vamos adicionar esse recurso à Intent.

    Primeiro, adiciono os modos compatíveis com a variável estática. Se eu definir segundo plano, isso informa ao sistema que a Intent nunca colocará o app em primeiro plano. No entanto, também quero que a Intent me leve ao app, se possível. Então adiciono o modo de primeiro plano, que pede ao sistema para abrir o app antes de executar a Intent.

    Posso usar a nova propriedade currentMode para verificar se estamos em primeiro plano. Se estivermos, podemos navegar dessa forma. Só um minuto. Por que ele informa que não há ninguém no ponto de referência? Ele está fechado. Vamos modificar a Intent para que ela não abra o app nesse cenário. No método perform, posso conferir se o ponto de referência está aberto e sair mais cedo se não estiver. Nesse caso, não quero que o app fique em primeiro plano antes de executar a Intent. Vou modificar o modo de primeiro plano para ser dinâmico. Os modos compatíveis disponíveis incluem segundo plano e três modos de primeiro plano. immediate orienta o sistema a colocar o app em primeiro plano antes de executar a Intent. dynamic permite que a Intent decida se deseja ou não abrir o app. E deferred indica que a Intent colocará o app em primeiro plano, mas não imediatamente. GetCrowdStatus pode não abrir o app, então o modo dinâmico é o ideal.

    Nesses dois modos, a Intent pode usar o método continueInForeground para controlar quando colocar o app em primeiro plano.

    Se o ponto de referência estiver aberto, usamos a nova propriedade em systemContext para verificar se o app pode ficar em primeiro plano. Se puder, chamaremos o método continueInForeground para fazer isso. Ao definir alwaysConfirm como false, o sistema evitará avisar se houve atividade nos últimos segundos. Se o app for aberto corretamente, podemos navegar até o status de lotação. No entanto, se a solicitação de abertura for negada, pelo sistema ou pelo usuário, o método gerará um erro. Você pode capturá-lo e manipulá-lo de acordo. Antes de encerrarmos, vamos explorar alguns aspectos que tornaram o desenvolvimento com App Intents mais fácil.

    Para a navegação na interface de usuário, as App Intents precisam ter acesso a todos os estados do app que controlam as visualizações. Isso é feito apenas com objetos compartilhados globalmente, como AppDependencies ou singletons. Com as novas APIs de controle de visualização, você pode remover o código de interface das App Intents para que as visualizações o manipulem por conta própria. Vamos usá-lo para refatorar a Intent para ponto de referência aberto. Primeiro, a Intent precisa estar em conformidade com o protocolo TargetContentProvidingIntent. Na visualização SwiftUI, tenho uma propriedade path que é usada para modificar a NavigationStack programaticamente. Como está marcada como um estado, só é possível acessá-la no corpo da visualização. É aqui que entra o modificador de visualização onAppIntentExecution. Ele pega o tipo de App Intent que você deseja manipular e um encerramento de ação com a Intent passada. Dentro, posso fazer referência aos parâmetros da Intent e modificar a interface de acordo. A implementação desse código permite remover o código de interface da própria Intent ou remover totalmente o método perform, além da dependência que não é mais necessária. Não é maravilhoso?

    O sistema executa o encerramento da ação pouco antes de colocar o app em primeiro plano. Portanto, você só pode ler os valores de parâmetro da Intent. Outras operações, como solicitação de valores, não são compatíveis. Se várias visualizações tiverem o mesmo modificador, todas serão executadas, para que cada uma possa responder de acordo. Se o app oferecer suporte a várias cenas ou janelas, convém controlar qual delas executa uma Intent específica. Por exemplo, ao editar uma coleção no app TravelTracking, não gostaria que ela navegasse para um ponto de referência com essa cena. Seria muito incômodo. Felizmente, posso controlar isso usando as APIs handlesExternalEvents. Um conteúdo de destino que fornece Intent tem a propriedade contentidentifier, cujo padrão é persistentidentifier. Geralmente, é o nome da Intent. Você pode personalizar esse valor para ser ainda mais específico.

    Podemos usá-lo com os modificadores HandlesExternalEvents em cenas para definir a condição de ativação. Ela orienta o sistema a usar a cena para executar a App Intent. Ele criará uma se ainda não existir. Verifique se o identificador na matriz corresponde à propriedade identificadora de conteúdo da Intent que você quer manipular. Se as condições de ativação forem dinâmicas, você poderá usar o mesmo modificador em visualizações. Estou permitindo que a cena manipule OpenLandmarkIntent somente se não estivermos editando uma coleção. Saiba mais sobre cenas SwiftUI e condições de ativação nestas duas sessões. Para UIKit, você pode adequar as Intents ao protocolo UISceneAppIntent, para que possam acessar UIScene com esses membros. Ou seu delegado de cena pode responder a uma execução de Intent após estar em conformidade com AppIntentSceneDelegate. Por fim, você também pode usar condições de ativação para decidir qual cena manipulará uma App Intent. A próxima melhoria é a nova macro ComputedProperty, que permite evitar o armazenamento de valores em AppEntities. Aqui está a SettingsEntity que copia o defaultPlace de UserDefaults. Quero evitar armazenar um valor duplicado na struct. Em vez disso, ela deve ser derivada diretamente da fonte da verdade. Com a nova macro ComputedProperty, posso conseguir isso acessando UserDefaults diretamente do getter.

    Também adicionamos uma nova macro DeferredProperty para reduzir o custo de instanciar uma AppEntity. Em LandmarkEntity, o valor da propriedade crowdStatus vem de um servidor de rede. Buscá-la é relativamente caro. Quero fazer a busca apenas se o sistema a solicitar explicitamente. Marcando essa propriedade como DeferredProperty, posso fornecer um getter assíncrono. Dentro, posso chamar métodos que fazem as chamadas de rede. Esse getter assíncrono só será chamado se recursos do sistema como Atalhos o solicitarem, não ao criar e passar LandmarkEntity.

    Aqui estão diferenças importantes entre os três tipos de propriedade. Em geral, escolha ComputedProperty em vez de Deferred para reduzir a sobrecarga do sistema. Só alterne para Deferred se a propriedade for muito cara para calcular. Agora você pode colocar suas App Intents em pacotes Swift.

    Já ativamos o empacotamento do código AppIntents com frameworks e bibliotecas dinâmicas. Agora você pode colocá-los em pacotes Swift e bibliotecas estáticas. Para saber mais sobre o uso do protocolo AppIntentsPackage, confira a sessão "Conhecer o App Intents". Espero que tenham gostado de aprender sobre esses recursos comigo. A seguir, teste snippets interativos para saber como funcionam com suas Intents. Associe entidades ao conteúdo na tela para que o sistema possa sugeri-las automaticamente ao usuário. Forneça mais opções para as pessoas escolherem usando a API de múltipla escolha. Disponibilize vários modos para que as Intents ofereçam a melhor experiência, não importa como sejam executadas. Para trabalhar mais o código, confira nosso app de exemplo no site de desenvolvedor. É incrível poder compartilhar tudo isso com vocês. Mal posso esperar pelas ideias criativas que vão surgir.

    Isso é tudo por enquanto. Agradeço sua participação.

    • 4:08 - Returning a Snippet Intent

      import AppIntents
      import SwiftUI
      
      struct ClosestLandmarkIntent: AppIntent {
          static let title: LocalizedStringResource = "Find Closest Landmark"
      
          @Dependency var modelData: ModelData
      
          func perform() async throws -> some ReturnsValue<LandmarkEntity> & ShowsSnippetIntent & ProvidesDialog {
              let landmark = await self.findClosestLandmark()
      
              return .result(
                  value: landmark,
                  dialog: IntentDialog(
                      full: "The closest landmark is \(landmark.name).",
                      supporting: "\(landmark.name) is located in \(landmark.continent)."
                  ),
                  snippetIntent: LandmarkSnippetIntent(landmark: landmark)
              )
          }
      }
    • 4:31 - Building a SnippetIntent

      struct LandmarkSnippetIntent: SnippetIntent {
          static let title: LocalizedStringResource = "Landmark Snippet"
      
          @Parameter var landmark: LandmarkEntity
          @Dependency var modelData: ModelData
      
          func perform() async throws -> some IntentResult & ShowsSnippetView {
              let isFavorite = await modelData.isFavorite(landmark)
      
              return .result(
                  view: LandmarkView(landmark: landmark, isFavorite: isFavorite)
              )
          }
      }
    • 5:45 - Associate intents with buttons

      struct LandmarkView: View {
          let landmark: LandmarkEntity
          let isFavorite: Bool
      
          var body: some View {
              // ...
              Button(intent: UpdateFavoritesIntent(landmark: landmark, isFavorite: !isFavorite)) { /* ... */ }
      
              Button(intent: FindTicketsIntent(landmark: landmark)) { /* ... */ }
              // ...
          }
      }
    • 6:53 - Request confirmation snippet

      struct FindTicketsIntent: AppIntent {
      
          func perform() async throws -> some IntentResult & ShowsSnippetIntent {
              let searchRequest = await searchEngine.createRequest(landmarkEntity: landmark)
      
              // Present a snippet that allows people to change
              // the number of tickets.
              try await requestConfirmation(
                  actionName: .search,
                  snippetIntent: TicketRequestSnippetIntent(searchRequest: searchRequest)
              )
      
              // Resume searching...
          }
      }
    • 7:24 - Using Entities as parameters

      struct TicketRequestSnippetIntent: SnippetIntent {
          static let title: LocalizedStringResource = "Ticket Request Snippet"
      
          @Parameter var searchRequest: SearchRequestEntity
      
          func perform() async throws -> some IntentResult & ShowsSnippetView {
              let view = TicketRequestView(searchRequest: searchRequest)
      
              return .result(view: view)
          }
      }
    • 8:01 - Updating a snippet

      func performRequest(request: SearchRequestEntity) async throws {
          // Set to pending status...
         
          TicketResultSnippetIntent.reload()
      
          // Kick off search...
      
          TicketResultSnippetIntent.reload()
      }
    • 9:24 - Responding to Image Search

      struct LandmarkIntentValueQuery: IntentValueQuery {
      
          @Dependency var modelData: ModelData
      
          func values(for input: SemanticContentDescriptor) async throws -> [LandmarkEntity] {
              guard let pixelBuffer: CVReadOnlyPixelBuffer = input.pixelBuffer else {
                  return []
              }
      
              let landmarks = try await modelData.searchLandmarks(matching: pixelBuffer)
      
              return landmarks
          }
      }
    • 9:51 - Support opening an entity

      struct OpenLandmarkIntent: OpenIntent {
          static var title: LocalizedStringResource = "Open Landmark"
      
          @Parameter(title: "Landmark")
          var target: LandmarkEntity
      
          func perform() async throws -> some IntentResult {
              /// ...
          }
      }
    • 10:53 - Show search results in app

      @AppIntent(schema: .visualIntelligence.semanticContentSearch)
      struct ShowSearchResultsIntent {
          var semanticContent: SemanticContentDescriptor
      
          @Dependency var navigator: Navigator
      
          func perform() async throws -> some IntentResult {
              await navigator.showImageSearch(semanticContent.pixelBuffer)
      
              return .result()
          }
      
          // ...
      }
    • 11:40 - Returning multiple entity types

      @UnionValue
      enum VisualSearchResult {
          case landmark(LandmarkEntity)
          case collection(CollectionEntity)
      }a
      
      struct LandmarkIntentValueQuery: IntentValueQuery {
          func values(for input: SemanticContentDescriptor) async throws -> [VisualSearchResult] {
              // ...
          }
      }
      
      struct OpenLandmarkIntent: OpenIntent { /* ... */ }
      struct OpenCollectionIntent: OpenIntent { /* ... */ }
    • 13:00 - Associating a view with an AppEntity

      struct LandmarkDetailView: View {
      
          let landmark: LandmarkEntity
      
          var body: some View {
              Group{ /* ... */ }
              .userActivity("com.landmarks.ViewingLandmark") { activity in
                  activity.title = "Viewing \(landmark.name)"
                  activity.appEntityIdentifier = EntityIdentifier(for: landmark)
              }
          }
      }
    • 13:21 - Converting AppEntity to PDF

      import CoreTransferable
      import PDFKit
      
      extension LandmarkEntity: Transferable {
          static var transferRepresentation: some TransferRepresentation {
              DataRepresentation(exportedContentType: .pdf) {landmark in
                  // Create PDF data...
                  return data
              }
          }
      }
    • 14:05 - Associating properties with Spotlight keys

      struct LandmarkEntity: IndexedEntity {
      
          // ...
      
          @Property(indexingKey: \.displayName)
          var name: String
      
          @Property(customIndexingKey: /* ... */)
          var continent: String
      
          // ...
      }
    • 15:49 - Making intents undoable

      struct DeleteCollectionIntent: UndoableIntent {
          // ...
      
          func perform() async throws -> some IntentResult {
      
              // Confirm deletion...
      
              await undoManager?.registerUndo(withTarget: modelData) {modelData in
                  // Restore collection...
              }
              await undoManager?.setActionName("Delete \(collection.name)")
      
             // Delete collection...
          }
      }
    • 16:52 - Multiple choice

      struct DeleteCollectionIntent: UndoableIntent {
          func perform() async throws -> some IntentResult & ReturnsValue<CollectionEntity?> {
              let archive = Option(title: "Archive", style: .default)
              let delete = Option(title: "Delete", style: .destructive)
      
              let resultChoice = try await requestChoice(
                  between: [.cancel, archive, delete],
                  dialog: "Do you want to archive or delete \(collection.name)?",
                  view: collectionSnippetView(collection)
              )
      
              switch resultChoice {
              case archive: // Archive collection...
              case delete: // Delete collection...
              default: // Do nothing...
              }
          }
          // ...
      }
    • 18:47 - Supported modes

      struct GetCrowdStatusIntent: AppIntent {
      
          static let supportedModes: IntentModes = [.background, .foreground]
      
          func perform() async throws -> some ReturnsValue<Int> & ProvidesDialog {
              if systemContext.currentMode == .foreground {
                  await navigator.navigateToCrowdStatus(landmark)
              }
      
              // Retrieve status and return dialog...
          }
      }
    • 19:30 - Supported modes

      struct GetCrowdStatusIntent: AppIntent {
          static let supportedModes: IntentModes = [.background, .foreground(.dynamic)]
      
          func perform() async throws -> some ReturnsValue<Int> & ProvidesDialog {
              guard await modelData.isOpen(landmark) else { /* Exit early... */ }
      
              if systemContext.currentMode.canContinueInForeground {
                  do {
                      try await continueInForeground(alwaysConfirm: false)
                      await navigator.navigateToCrowdStatus(landmark)
                  } catch {
                      // Open app denied.
                  }
              }
      
              // Retrieve status and return dialog...
          }
      }
    • 21:30 - View Control

      extension OpenLandmarkIntent: TargetContentProvidingIntent {}
      
      struct LandmarksNavigationStack: View {
      
          @State var path: [Landmark] = []
      
          var body: some View {
              NavigationStack(path: $path) { /* ... */ }
              .onAppIntentExecution(OpenLandmarkIntent.self) { intent in
                  self.path.append(intent.landmark)
              }
          }
      }
    • 23:13 - Scene activation condition

      @main
      struct AppIntentsTravelTrackerApp: App {
          var body: some Scene {
              WindowGroup { /* ... */ }
      
              WindowGroup { /* ... */ }
              .handlesExternalEvents(matching: [
                  OpenLandmarkIntent.persistentIdentifier
              ])
          }
      }
    • 23:33 - View activation condition

      struct LandmarksNavigationStack: View {
          var body: some View {
              NavigationStack(path: $path) { /* ... */ }
              .handlesExternalEvents(
                  preferring: [],
                  allowing: !isEditing ? [OpenLandmarkIntent.persistentIdentifier] : []
              )
          }
      }
    • 24:23 - Computed property

      struct SettingsEntity: UniqueAppEntity {
      
          @ComputedProperty
          var defaultPlace: PlaceDescriptor {
              UserDefaults.standard.defaultPlace
          }
      
          init() {
          }
      }
    • 24:48 - Deferred property

      struct LandmarkEntity: IndexedEntity {
          // ...
      
          @DeferredProperty
          var crowdStatus: Int {
              get async throws {
                  await modelData.getCrowdStatus(self)
              }
          }
      
          // ...
      }
    • 25:50 - AppIntentsPackage

      // Framework or dynamic library
      public struct LandmarksKitPackage: AppIntentsPackage { }
      
      // App target
      struct LandmarksPackage: AppIntentsPackage {
          static var includedPackages: [any AppIntentsPackage.Type] {
              [LandmarksKitPackage.self]
          }
      }
    • 0:00 - Introdução
    • O App Intents é um framework que permite aos apps integrar recursos entre dispositivos, como Atalhos, Spotlight e Inteligência Visual. Saiba mais sobre os novos fragmentos interativos, a integração com apps em todo o sistema, as experiências do usuário aprimoradas e as APIs práticas para desenvolvedores.

    • 0:55 - Snippets interativos
    • Com as atualizações mais recentes, agora você pode aprimorar seus apps com fragmentos interativos. Eles são visualizações dinâmicas que exibem informações personalizadas com base no App Intents. Por exemplo, um app de jardinagem pode sugerir ligar os sprinklers, e um app de pedidos de comida pode permitir que a pessoa personalize o pedido antes de finalizá-lo. O app de exemplo TravelTracking ilustra bem esse caso. Quando um usuário pesquisa o ponto turístico mais próximo, um fragmento interativo aparece. Ele inclui o nome do ponto turístico e um botão de coração. Ao tocar no botão de coração, a pessoa pode adicionar o ponto turístico aos favoritos e o fragmento é atualizado instantaneamente para refletir esse novo status. Tudo isso sem sair da visualização atual. Essa interatividade é possível graças ao novo protocolo SnippetIntent. Com ele, é possível criar fragmentos de resultado que exibem informações após uma ação, e esses fragmentos podem incluir botões ou controles que acionam outros App Intents. Por exemplo, no app TravelTracking, o botão de coração executa a Intent Atualizar Favoritos, e você pode adicionar um botão Encontrar Passagens para acionar outra Intent. Quando alguém interage com esses botões, o sistema executa a Intent correspondente e o fragmento é atualizado, conforme necessário. O sistema garante que os dados estejam sempre atualizados ao buscar entidades do app por meio de consultas sempre que o fragmento é atualizado. Esse processo é contínuo e animado, oferecendo uma experiência de uso fluida. Você também pode criar fragmentos de confirmação que solicitam informações adicionais antes de continuar. Por exemplo, no app TravelTracking, quando alguém toca em Encontrar Passagens, aparece um fragmento de confirmação pedindo quantos ingressos a pessoa deseja procurar. Em seguida, a pessoa pode interagir com esse fragmento, e o sistema atualiza a visualização em tempo real com base nas entradas.

    • 8:15 - Novas integrações do sistemas
    • O App Intents no iOS 26 aprimora a integração do sistema, permitindo a pesquisa de imagens diretamente usando gravações da câmera ou capturas de tela. Agora, os apps podem exibir os resultados da busca no painel de pesquisa do sistema. Para possibilitar essa funcionalidade, implemente consultas que estejam em conformidade com o protocolo IntentValueQuery, processando dados do SemanticContentDescriptor para retornar matrizes de entidades do app. Quando alguém toca em um resultado, a OpenIntent correspondente é acionada, abrindo o app na página relevante. As OpenIntents não se limitam à busca de imagens. Você também pode usá-las no Spotlight. Considere otimizar o desempenho da pesquisa, retornar várias páginas de resultados e permitir que a pessoa continue a busca dentro do app. Além da busca de imagens, o App Intents também é compatível com entidades visíveis na tela, permitindo que as pessoas interajam com a Siri e o ChatGPT sobre o conteúdo mostrado no app. É possível associar entidades a visualizações, fazê-las adotar o protocolo Transferable e aceitar diversos tipos de dados, como PDF, texto simples e texto com formatação. Para aprimorar a busca no Spotlight, faça com que as entidades do app adotem o protocolo IndexedEntity, doe essas entidades ao Spotlight e anote o conteúdo exibido na tela com elas. A implementação do protocolo PredictableIntent permite que o sistema aprenda com o comportamento do usuário e forneça sugestões personalizadas.

    • 15:01 - Melhorias na experiência do usuário
    • Os novos recursos da plataforma de desenvolvimento de apps aprimoram a experiência do usuário com melhorias na funcionalidade de desfazer, opções de múltipla escolha e modos compatíveis. O protocolo UndoableIntent permite que as pessoas revertam ações realizadas com o App Intents usando gestos já conhecidos, oferecendo uma rede de segurança para experimentações. Para implementar, basta fazer com que as Intents adotem o protocolo, além de registrar ações de desfazer com o Undo Manager. Com a API multiple-choice, é possível apresentar várias opções para uma Intent em vez de apenas uma confirmação binária. Você também pode personalizar a experiência com uma caixa de diálogo e uma view da SwiftUI personalizada. Os modos compatíveis oferecem às Intents mais controle sobre a abertura do app em primeiro plano. Essa funcionalidade permite que as Intents se comportem de maneiras diferentes, dependendo de como a pessoa interage com o dispositivo. Por exemplo, uma Intent pode fornecer informações apenas por voz quando a pessoa estiver dirigindo, mas levá-la diretamente ao app quando ela estiver olhando para a tela. Você pode definir os modos compatíveis para as Intents e usar a propriedade currentMode para verificar qual modo está ativo.

    • 21:02 - APIs de conveniência
    • Com as novas APIs de controle de view na SwiftUI, você pode refatorar seus App Intents removendo o código de interface e permitindo que as visualizações lidem diretamente com a navegação. Use o modificador de view onAppIntentExecution, que permite que as visualizações respondam a App Intents específicos e modifiquem a interface conforme necessário. O sistema executa o bloco de ação pouco antes de trazer o app para o primeiro plano, e várias visualizações podem responder à mesma Intent. É possível escolher qual cena deve lidar com uma Intent usando as APIs handlesExternalEvents, o que garante uma navegação adequada ao contexto. Além disso, novas macros como ComputedProperty e DeferredProperty otimizam AppEntities, reduzindo os custos de armazenamento e instanciação. Agora, os App Intents também podem ser agrupados em pacotes do Swift, oferecendo mais flexibilidade e reusabilidade.

Developer Footer

  • Vídeos
  • WWDC25
  • Explore os novos avanços do framework App Intents
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • App Store
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Fonts
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Open Source
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Sample Code
    • Tutorials
    • Downloads
    • Forums
    • Videos
    Open Menu Close Menu
    • Support Articles
    • Contact Us
    • Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Get the Apple Developer app.
    Copyright © 2025 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines