Foundation Models no iOS 26: Guia Completo de IA On-Device com Swift

Guia completo do Foundation Models no iOS 26. Aprenda a usar IA on-device nos seus apps SwiftUI com @Generable, streaming e Tool Calling — sem API keys, sem custos, tudo no dispositivo.

Se você é desenvolvedor iOS, com certeza já ouviu falar do Foundation Models framework — provavelmente a novidade mais empolgante da WWDC 2025 pra quem trabalha com Swift. E olha, não é exagero. Pela primeira vez, a Apple abriu acesso direto ao modelo de linguagem por trás do Apple Intelligence, e a melhor parte: tudo roda no próprio dispositivo. Sem API keys. Sem custos de nuvem. Sem internet. Privacidade total.

Neste guia, vou cobrir tudo que você precisa pra começar a usar o Foundation Models nos seus apps — da configuração inicial até recursos avançados como Guided Generation com @Generable, streaming de respostas e Tool Calling. Se você quer adicionar IA nativa aos seus projetos SwiftUI sem depender de serviços externos, cola aqui.

O Que é o Foundation Models Framework?

O Foundation Models é um framework que chegou no iOS 26 e dá aos desenvolvedores acesso ao modelo de linguagem on-device da Apple — estamos falando de um LLM com aproximadamente 3 bilhões de parâmetros. É o mesmo modelo que já alimenta funcionalidades do Apple Intelligence como resumo de textos, sugestões inteligentes e respostas automáticas.

Diferente de soluções na nuvem como ChatGPT ou Claude, que dependem de servidores remotos e conexão com a internet, o modelo da Apple roda inteiramente no hardware do usuário, aproveitando o Apple Silicon. Na prática, isso traz três vantagens bem claras:

  • Privacidade absoluta — nenhum dado sai do dispositivo do usuário
  • Latência mínima — sem roundtrips de rede, as respostas chegam bem mais rápido
  • Funciona offline — o modelo opera sem qualquer conexão com a internet

O framework está disponível pra iOS 26, iPadOS 26, macOS Tahoe e visionOS 26, e suporta 10 idiomas nativamente — incluindo português.

Requisitos e Configuração Inicial

Antes de meter a mão na massa, confira se seu ambiente tá pronto:

  • Xcode 26 instalado (disponível no Mac App Store ou no site da Apple)
  • macOS Tahoe (macOS 26) ou superior
  • Dispositivo com Apple Silicon (iPhone 15 Pro ou superior, iPad com chip M1+, Mac com Apple Silicon)
  • Apple Intelligence ativado nas configurações do sistema

Com tudo certo, o primeiro passo é importar o framework:

import FoundationModels

Só isso. Sem dependências externas, sem pods, sem SPM packages. O framework já vem integrado ao SDK do iOS 26. Confesso que quando vi isso pela primeira vez, achei quase bom demais pra ser verdade.

Verificando a Disponibilidade do Modelo

Nem todo dispositivo suporta o Foundation Models — e esse é um detalhe que muita gente esquece. Antes de usar qualquer funcionalidade, você precisa verificar se o modelo tá disponível. A Apple fornece uma API pra isso através do SystemLanguageModel:

let model = SystemLanguageModel.default

switch model.availability {
case .available:
    // Modelo pronto — pode mostrar a UI principal
    print("Modelo disponível!")
case .unavailable(let reason):
    switch reason {
    case .deviceNotEligible:
        print("Este dispositivo não suporta Apple Intelligence.")
    case .appleIntelligenceNotEnabled:
        print("Ative o Apple Intelligence nas Configurações.")
    case .modelNotReady:
        print("O modelo está sendo baixado. Tente novamente em breve.")
    @unknown default:
        print("Modelo indisponível.")
    }
}

São três razões possíveis pra indisponibilidade:

  • deviceNotEligible — o hardware não suporta (chips mais antigos, basicamente)
  • appleIntelligenceNotEnabled — o usuário ainda não ativou o Apple Intelligence
  • modelNotReady — o modelo tá sendo baixado ou o sistema bloqueou temporariamente (bateria baixa, Modo Jogo ativo, essas coisas)

Num app de produção, use essa verificação pra adaptar a UI. Sempre ofereça um fallback — não deixe o usuário num beco sem saída.

Primeira Interação: LanguageModelSession

O LanguageModelSession é o coração da coisa toda. Pense nele como uma sessão de conversa — você manda perguntas, recebe respostas. Simples assim.

Uso Básico (Single-Turn)

let session = LanguageModelSession()
let response = try await session.respond(to: "Explique o padrão MVVM em Swift")
print(response.content)

Três linhas de código. Só três. E você já tá interagindo com um LLM de 3 bilhões de parâmetros rodando no dispositivo. A resposta vem como String, pronta pra renderizar na UI.

Conversas Multi-Turn

Pra manter o contexto entre perguntas — tipo uma conversa de verdade — declare a sessão como variável de estado no SwiftUI:

struct ChatView: View {
    @State private var session = LanguageModelSession()
    @State private var question = ""
    @State private var answer = ""

    var body: some View {
        VStack(spacing: 16) {
            ScrollView {
                Text(LocalizedStringKey(answer))
                    .padding()
            }

            HStack {
                TextField("Faça uma pergunta...", text: $question)
                    .textFieldStyle(.roundedBorder)

                Button("Enviar") {
                    Task {
                        let response = try await session.respond(to: question)
                        answer = response.content
                    }
                }
                .disabled(session.isResponding)
            }
            .padding()
        }
    }
}

Ao reutilizar a mesma instância de LanguageModelSession, o modelo mantém o histórico da conversa. Perguntas de acompanhamento funcionam naturalmente — ele entende referências a respostas anteriores sem problema.

E aquela propriedade isResponding? Super útil. Use pra desabilitar botões enquanto o modelo gera a resposta. Evita aquele bug clássico de requisição duplicada.

Instruções Personalizadas

Você pode configurar o comportamento do modelo com instruções na criação da sessão:

let session = LanguageModelSession(
    instructions: "Você é um assistente especializado em receitas brasileiras. Responda sempre em português, com medidas no sistema métrico."
)

Funciona como um system prompt — define o papel, o tom e os limites antes de qualquer interação do usuário. Honestamente, com boas instruções o modelo surpreende bastante, mesmo sendo "só" 3B de parâmetros.

Streaming de Respostas

Ficar esperando a resposta completa antes de mostrar qualquer coisa na tela é uma experiência péssima pro usuário (e convenhamos, pra qualquer pessoa). O Foundation Models resolve isso com streaming nativo — as respostas vão aparecendo progressivamente, palavra por palavra, do jeitinho que você já viu no ChatGPT.

func generateAnswer() async {
    do {
        answer = ""
        let stream = session.streamResponse(to: question)
        for try await partialResponse in stream {
            answer = partialResponse.asPartiallyGenerated()
        }
    } catch {
        answer = "Erro ao gerar resposta: \(error.localizedDescription)"
    }
}

O streamResponse(to:) retorna um AsyncSequence que emite fragmentos parciais da resposta. A cada iteração, você atualiza a view e o usuário vê o texto sendo "digitado" em tempo real.

Essa abordagem é genial porque transforma latência em experiência. Em vez de um spinner girando sem fim, o usuário já começa a ler enquanto o modelo continua trabalhando.

Guided Generation: Respostas Tipadas com @Generable

Até aqui, trabalhamos com respostas em texto livre — strings puras. Mas e quando você precisa de dados estruturados? Um objeto Swift com propriedades certinhas, pronto pra usar na UI ou salvar no banco?

É aí que entra o Guided Generation, e na minha opinião é o recurso mais poderoso de todo o framework. Com o macro @Generable, você define a estrutura de saída que quer e o modelo gera os dados diretamente como um tipo Swift nativo.

Definindo um Tipo @Generable

import FoundationModels

@Generable
struct QuizQuestion {
    let text: String
    let choices: [String]
    let answer: String
    let explanation: String
}

O macro @Generable gera automaticamente um schema JSON em tempo de compilação. Quando o modelo retorna a resposta, ela é decodificada direto no seu tipo Swift. Sem parsing manual, sem regex, sem surpresas desagradáveis.

Gerando uma Instância

let session = LanguageModelSession(
    instructions: "Você é um professor de história do Brasil."
)

let response = try await session.respond(
    to: "Crie uma pergunta sobre a Proclamação da República",
    generating: QuizQuestion.self
)

let question = response.content
print(question.text)       // A pergunta gerada
print(question.choices)    // Array com as opções
print(question.answer)     // A resposta correta
print(question.explanation) // Explicação detalhada

O parâmetro generating: diz ao modelo exatamente qual estrutura preencher. O resultado é type-safe — acesse propriedades diretamente, sem casting ou unwrapping de JSON. É a integração que todo dev Swift sonhava.

Refinando com @Guide

Quer mais controle? O macro @Guide permite adicionar restrições e descrições em propriedades individuais:

@Generable
struct QuizQuestion {
    @Guide(description: "A pergunta do quiz, clara e objetiva")
    let text: String

    @Guide(.count(4), description: "Exatamente 4 alternativas")
    let choices: [String]

    @Guide(description: "A alternativa correta, idêntica a uma das choices")
    let answer: String

    @Guide(description: "Explicação breve de por que essa é a resposta correta")
    let explanation: String
}

As restrições disponíveis incluem:

  • .count(n) — tamanho exato do array
  • .minimumCount(n) — mínimo de elementos
  • .maximumCount(n) — máximo de elementos
  • .range(min...max) — intervalo numérico
  • description: — contexto textual pra qualquer propriedade

Detalhe importante: a ordem das propriedades importa (e muito). O modelo gera os valores sequencialmente, então propriedades que dependem de outras — como explanation, que faz referência a answer — precisam ser declaradas depois.

Enums Também Funcionam

@Generable
enum Difficulty: String, Codable {
    case facil
    case medio
    case dificil
}

Enums com @Generable restringem a saída do modelo aos cases definidos — perfeito pra classificações e categorizações onde você não quer que o modelo invente valores aleatórios.

Streaming com Guided Generation

E aqui fica ainda melhor: Guided Generation e streaming combinam perfeitamente. O modelo gera as propriedades uma a uma e você recebe snapshots parciais:

let stream = session.streamResponse(
    to: "Sugira 3 receitas com frango",
    generating: [Recipe].self
)

for try await partialRecipes in stream {
    recipes = partialRecipes // Atualiza a UI progressivamente
}

A cada iteração, mais propriedades vão sendo preenchidas. Dá pra animar as transições na UI conforme os dados chegam — uma experiência muito mais rica que ficar olhando pra um loading spinner.

Tool Calling: Estendendo as Capacidades do Modelo

O modelo on-device é impressionante, mas convenhamos — ele tem limitações. Não acessa a internet, não sabe a previsão do tempo e não conhece os dados específicos do seu app. O Tool Calling resolve justamente isso, permitindo que o modelo invoque funções do seu código quando precisa de informações externas.

Pense em tools como superpoderes que você empresta ao modelo. Ele decide quando usar e você controla a implementação.

Criando uma Tool

Pra criar uma tool, implemente o protocolo Tool:

import FoundationModels

struct WeatherTool: Tool {
    let name = "getWeather"
    let description = "Obtém a previsão do tempo atual para uma cidade específica"

    @Generable
    struct Arguments {
        @Guide(description: "Nome da cidade para consultar o clima")
        let city: String
    }

    func call(arguments: Arguments) async throws -> String {
        // Aqui você implementa a lógica real
        // Ex: chamar WeatherKit, uma API REST, etc.
        let weather = try await WeatherService.fetch(for: arguments.city)
        return "Em \(arguments.city): \(weather.temperature)°C, \(weather.condition)"
    }
}

Uma tool precisa de três coisas:

  • name — identificador curto, sem espaços (é assim que o modelo referencia a tool internamente)
  • description — descrição legível do que ela faz
  • Arguments — struct @Generable com os parâmetros que o modelo vai preencher

Registrando Tools na Sessão

let session = LanguageModelSession(
    tools: [WeatherTool()],
    instructions: "Quando o usuário perguntar sobre o clima, use a tool getWeather."
)

Pode registrar várias tools de uma vez:

let session = LanguageModelSession(
    tools: [WeatherTool(), TranslationTool(), ContactsTool()],
    instructions: "Use as ferramentas disponíveis quando necessário para responder o usuário."
)

O modelo decide sozinho quando invocar cada tool, baseado na pergunta do usuário e na descrição que você forneceu. É surpreendentemente bom nisso, diga-se de passagem.

Integração Completa com SwiftUI

Bora juntar tudo num exemplo prático? Aqui vai um mini app de assistente culinário usando Guided Generation, streaming e instruções personalizadas:

import SwiftUI
import FoundationModels

@Generable
struct Recipe {
    @Guide(description: "Nome da receita")
    let name: String
    @Guide(description: "Tempo de preparo em minutos", .range(5...120))
    let prepTimeMinutes: Int
    @Guide(description: "Lista de ingredientes com quantidades")
    let ingredients: [String]
    @Guide(description: "Passo a passo do preparo")
    let steps: [String]
}

@MainActor
@Observable
class RecipeAssistant {
    var recipes: [Recipe.PartiallyGenerated] = []
    var isLoading = false

    private let session = LanguageModelSession(
        instructions: "Você é um chef brasileiro especializado em culinária caseira."
    )

    func suggest(ingredients: String) async {
        isLoading = true
        defer { isLoading = false }

        do {
            let prompt = "Sugira 2 receitas usando: \(ingredients)"
            let stream = session.streamResponse(
                to: prompt,
                generating: [Recipe].self
            )
            for try await partial in stream {
                recipes = partial
            }
        } catch {
            print("Erro: \(error.localizedDescription)")
        }
    }
}

struct RecipeView: View {
    @State private var assistant = RecipeAssistant()
    @State private var ingredients = ""

    var body: some View {
        NavigationStack {
            VStack(spacing: 16) {
                TextField("Ingredientes (ex: frango, arroz)", text: $ingredients)
                    .textFieldStyle(.roundedBorder)
                    .padding(.horizontal)

                Button("Sugerir Receitas") {
                    Task { await assistant.suggest(ingredients: ingredients) }
                }
                .buttonStyle(.borderedProminent)
                .disabled(assistant.isLoading || ingredients.isEmpty)

                List(assistant.recipes, id: \.name) { recipe in
                    VStack(alignment: .leading, spacing: 8) {
                        Text(recipe.name ?? "Gerando...")
                            .font(.headline)
                        if let time = recipe.prepTimeMinutes {
                            Text("\(time) minutos")
                                .font(.caption)
                                .foregroundStyle(.secondary)
                        }
                    }
                }
            }
            .navigationTitle("Chef IA")
        }
    }
}

Esse exemplo demonstra o padrão recomendado pela Apple: uma classe @Observable encapsulando a sessão e a lógica, e uma view SwiftUI observando as mudanças. O streaming com Recipe.PartiallyGenerated permite que a UI atualize em tempo real — conforme as receitas vão sendo geradas, o usuário já consegue ver o progresso.

Otimização de Performance

O modelo on-device impressiona, mas tem limitações reais que você precisa considerar antes de ir pra produção. Vou listar as principais.

Janela de Contexto

O modelo trabalha com uma janela de 4.096 tokens (entrada + saída combinadas). Parece pouco? É porque é. Prompts muito longos comem o espaço da resposta, então seja conciso nas instruções.

Prewarm pra Melhor Latência

Se você sabe que o usuário vai interagir com o modelo em breve, pré-aqueça a sessão:

session.prewarm() // Carrega recursos na memória antecipadamente

Isso faz uma diferença real no tempo da primeira resposta. Vale muito a pena.

Mantenha Structs @Generable Enxutas

Toda propriedade num tipo @Generable será gerada pelo modelo — mesmo que você não use na UI. Se uma view precisa só do nome e do tempo de preparo, não inclua passos detalhados e ingredientes. Crie tipos @Generable específicos pra cada contexto. Sério, isso muda bastante a performance.

Ordem das Propriedades

O modelo gera propriedades sequencialmente. Coloque resumos e campos derivados por último — dá mais contexto pro modelo gerá-los com qualidade.

Idioma das Instruções

Embora o modelo suporte português nos prompts do usuário, as instruções (system prompt) tendem a dar resultados melhores em inglês. Na prática, escreva as instruções em inglês e oriente o modelo a responder em português. Testei bastante e a diferença é perceptível.

Limitações que Você Precisa Conhecer

Antes de sair adicionando IA em tudo quanto é tela, é bom ter clareza sobre o que o Foundation Models não faz:

  • Requisito de hardware — só funciona em dispositivos com Apple Silicon que suportam Apple Intelligence
  • Modelo fixo — você não pode trocar por outro modelo, ajustar pesos ou fazer fine-tuning
  • Contexto limitado — 4.096 tokens é bem menos que modelos na nuvem (que chegam a 128K+)
  • Sem acesso à internet — o modelo não busca informações em tempo real (pra isso, use Tool Calling)
  • Condições do dispositivo — bateria baixa, Modo Jogo ou download em andamento podem bloquear o uso
  • Qualidade inferior a modelos maiores — com 3B de parâmetros, não espere o nível de um GPT-4 ou Claude. Pra tarefas focadas é excelente, mas raciocínio complexo não é o forte dele

Foundation Models vs. APIs de Nuvem: Quando Usar Cada Um?

Essa é uma dúvida que aparece sempre: quando usar o Foundation Models e quando recorrer a APIs como OpenAI ou Anthropic? A real é que depende do caso de uso:

Cenário Foundation Models APIs de Nuvem
Privacidade crítica (saúde, finanças) Ideal Requer cuidado extra
Funcionar offline Ideal Não suporta
Custo zero de inferência Gratuito Pago por token
Raciocínio complexo / textos longos Limitado Superior
Conhecimento atualizado Limitado ao treinamento Mais atual (com busca web)
Multimodal (imagens, áudio) Texto apenas Suporte amplo

Na prática, muitos apps vão combinar as duas abordagens — Foundation Models pras tarefas rápidas e sensíveis à privacidade, e nuvem pros cenários mais pesados. Não precisa ser uma coisa ou outra.

Perguntas Frequentes (FAQ)

O Foundation Models framework funciona em todos os iPhones?

Não. O framework requer dispositivos com Apple Silicon que suportem Apple Intelligence. Na prática: iPhone 15 Pro ou superior, iPads com chip M1+ e Macs com Apple Silicon. Dispositivos mais antigos simplesmente não têm o hardware pra rodar um modelo de 3 bilhões de parâmetros localmente.

Preciso pagar para usar o Foundation Models?

Não, e essa é uma das partes mais legais. O Foundation Models é 100% gratuito. Como roda no dispositivo do usuário, não tem custos de API, limites de tokens nem assinaturas. Importou o framework, já pode usar.

O Foundation Models funciona sem internet?

Sim! Essa é talvez a maior vantagem. Depois do download inicial do modelo (que acontece automaticamente quando o Apple Intelligence é ativado), todas as inferências rodam completamente offline. Funciona no avião, no metrô, em qualquer lugar sem sinal.

Posso usar o Foundation Models com Core Data ou SwiftData?

Pode, mas com uma ressalva. Como os tipos @Generable são structs, não dá pra usá-los diretamente como modelos do SwiftData (que exige classes @Model). O caminho é gerar os dados com @Generable e depois mapear pra seus modelos de persistência. Um passo a mais, mas funciona bem.

O modelo suporta português nativamente?

Sim. O Foundation Models suporta 10 idiomas, incluindo português. Pode mandar prompts em português e receber respostas no mesmo idioma tranquilamente. Só uma dica: as instruções do sistema (system prompt) costumam funcionar melhor em inglês — vale testar no seu caso.

Sobre o Autor Editorial Team

Our team of expert writers and editors.