Para criar pré-visualizações interativas do SwiftUI, dê a cada pré-visualização seu próprio estado local, passe um modelo de visualização observável ao editor e exponha as propriedades editáveis por meio de bindings. Este passo a passo cria um pequeno editor de rótulos para macOS usando texto de exemplo sintético.

Escolha onde o estado da pré-visualização deve ficar

A tarefa é pré-visualizar um editor para computador no qual alguém altera o título e o texto de detalhe de um rótulo e, em seguida, alterna a exibição do detalhe. O editor deve responder imediatamente, e cada pré-visualização deve começar com uma configuração de exemplo explícita.

Use a entrada mais simples que permita a interação. A Apple recomenda passar às views apenas os dados de que precisam, pois dependências complexas dificultam a construção das pré-visualizações. Um rótulo estático pode receber uma string; um editor precisa de uma conexão gravável com seu estado. Adicionando pré-visualizações aos arquivos da sua interface.

O que a view precisa Entrada adequada Onde deve ficar o estado de exemplo
Exibir texto fixo Uma string imutável Diretamente na pré-visualização
Editar um valor pertencente ao elemento pai Uma propriedade @Binding @State local no host da pré-visualização
Editar várias propriedades observáveis relacionadas Um modelo observável exposto por meio de @Bindable Uma instância do modelo armazenada em @State no host da pré-visualização
Ler um modelo fornecido pelo ambiente Uma dependência do ambiente Injeção explícita na raiz da pré-visualização

Neste exemplo, o modelo de visualização contém duas strings, uma configuração de visibilidade e um título de exibição calculado. Cada pré-visualização tem sua própria instância. Assim, as condições iniciais ficam visíveis ao lado da declaração da pré-visualização, e o exemplo não depende de um singleton mutável compartilhado.

Prepare um destino SwiftUI para macOS

Use o Xcode 16 ou posterior para a sintaxe inline @Previewable mostrada aqui. A Apple introduziu essa macro no Xcode 16. Defina o destino de implantação deste exemplo como macOS 14 ou posterior, versão em que o SwiftUI oferece suporte a Observation; a referência atual da Apple sobre Previewable() também indica a disponibilidade no macOS 14. Notas de versão do Xcode 16, Gerenciando os dados do modelo no seu app, Previewable().

Adicione um arquivo Swift chamado LabelEditor.swift a um destino existente de app SwiftUI para macOS. Os dois próximos blocos de código formam juntos o exemplo completo de pré-visualização. Mantenha o ponto de entrada existente do app; este arquivo define o modelo, o editor e as pré-visualizações.

O código usa a grafia @State em todas as cadeias de ferramentas compatíveis. A documentação atual da Apple diferencia as implementações: o Xcode 26 e versões anteriores usam o wrapper de propriedade State, enquanto o Xcode 27 e versões posteriores usam a macro State(). Tenha essa distinção em mente ao inspecionar o código gerado ou analisar os custos de inicialização. State, State().

Crie o modelo observável e a view editável

Aplique @Observable ao modelo para que o SwiftUI possa acompanhar as propriedades lidas pela interface. Use @Bindable no editor para criar os bindings das propriedades exigidos pelos campos de texto e pelo toggle. A Apple documenta essa combinação para editar modelos observáveis. Gerenciando os dados do modelo no seu app, Bindable.

import Foundation
import Observation
import SwiftUI

@MainActor
@Observable
final class LabelViewModel {
    var title: String
    var detail: String
    var showsDetail: Bool

    init(
        title: String,
        detail: String,
        showsDetail: Bool = true
    ) {
        self.title = title
        self.detail = detail
        self.showsDetail = showsDetail
    }

    var displayedTitle: String {
        let trimmed = title.trimmingCharacters(
            in: .whitespacesAndNewlines
        )
        return trimmed.isEmpty ? "Untitled label" : trimmed
    }
}

@MainActor
struct LabelEditor: View {
    @Bindable var model: LabelViewModel

    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            VStack(alignment: .leading, spacing: 6) {
                Text("Title")
                TextField("Label title", text: $model.title)
            }

            VStack(alignment: .leading, spacing: 6) {
                Text("Detail")
                TextField("Label detail", text: $model.detail)
            }

            Toggle("Show detail", isOn: $model.showsDetail)

            Divider()

            Text("Rendered label")
                .font(.caption)
                .foregroundStyle(.secondary)

            VStack(alignment: .leading, spacing: 8) {
                Text(model.displayedTitle)
                    .font(.title2)
                    .fixedSize(horizontal: false, vertical: true)

                if model.showsDetail {
                    Text(model.detail)
                        .foregroundStyle(.secondary)
                        .fixedSize(horizontal: false, vertical: true)
                }
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding()
            .background(
                .quaternary,
                in: RoundedRectangle(cornerRadius: 10)
            )
        }
        .textFieldStyle(.roundedBorder)
        .padding(20)
    }
}

O modelo recebe deliberadamente todos os valores de exemplo por meio do inicializador. O inicializador apenas atribui valores às propriedades locais. O cálculo alternativo muda o que o rótulo renderizado exibe sem substituir o título digitado por alguém: um título que contenha apenas espaços em branco continua editável, enquanto o resultado renderizado mostra Untitled label.

O editor recebe seu modelo de quem o chama. A declaração @Bindable fornece bindings como $model.title; a propriedade do estado fica no host da pré-visualização. Se essa view apenas exibisse os valores do modelo, uma referência simples ao modelo bastaria para observá-lo. O armazenamento Bindable é útil aqui porque os controles precisam de bindings graváveis das propriedades. Bindable.

Dê a cada pré-visualização um estado de exemplo independente

Acrescente as declarações a seguir ao mesmo arquivo. Cada uma cria seu próprio modelo com valores sintéticos explícitos. As larguras servem como verificações ilustrativas de layout, não como tamanhos mínimos recomendados para a janela.

#Preview("Standard label") {
    @Previewable @State var model = LabelViewModel(
        title: "Sample tile",
        detail: "Blue square, medium size"
    )

    LabelEditor(model: model)
        .frame(width: 420)
        .preferredColorScheme(.light)
}

#Preview("Long label in a narrow editor") {
    @Previewable @State var model = LabelViewModel(
        title: "Sample collection with a longer descriptive label",
        detail: "Round tiles arranged in three columns"
    )

    LabelEditor(model: model)
        .frame(width: 300)
        .preferredColorScheme(.dark)
}

#Preview("Blank title and hidden detail") {
    @Previewable @State var model = LabelViewModel(
        title: "   ",
        detail: "An optional detail line",
        showsDetail: false
    )

    LabelEditor(model: model)
        .frame(width: 420)
}

@Previewable faz com que a declaração do estado local passe a fazer parte de uma view SwiftUI incorporada, gerada por #Preview. A Apple documenta que as declarações marcadas se tornam propriedades dessa view gerada. Coloque a declaração na raiz do closure da pré-visualização; usar @Previewable fora do corpo de uma pré-visualização é um erro. Previewable().

A cadeia de propriedade resultante é explícita: o host de pré-visualização gerado armazena o modelo em @State, LabelEditor recebe a referência ao modelo e @Bindable expõe suas propriedades editáveis. O SwiftUI permite armazenar um modelo de Observation em state e passar essa referência às views filhas. State.

Trate os valores do inicializador como dados iniciais de exemplo. Uma pré-visualização interativa pode alterá-los durante a execução. Ao reproduzir um layout específico, volte a uma instância nova da pré-visualização antes de comparar sua aparência inicial.

Verifique o comportamento com uma pequena matriz de cenários

Abra LabelEditor.swift, escolha Show Canvas e selecione uma pré-visualização nomeada nas abas do canvas. Se o canvas estiver pausado, use Restart. Ative o modo Live para testar a entrada de texto e a lógica dos controles. Esses controles são descritos no guia atual da Apple sobre o canvas. Interagindo com pré-visualizações no canvas.

Use as verificações a seguir para diferenciar problemas de estado de problemas de layout. Os resultados esperados decorrem do código de exemplo; não são resultados de testes relatados.

Cenário Ação Resultado esperado
Rótulo padrão Substitua o título por Amber circle O título renderizado muda imediatamente
Visibilidade do detalhe Desative Show detail e depois ative novamente O detalhe desaparece e volta com o texto preservado
Título vazio Remova todos os caracteres do título O título renderizado passa a ser Untitled label
Título com espaços em branco Digite apenas espaços O campo mantém esses espaços; o título renderizado usa o valor alternativo
Editor estreito Examine a pré-visualização com título longo O título renderizado quebra linhas dentro do cartão
Dados de exemplo separados Edite uma pré-visualização e, em seguida, examine outra pré-visualização nova A outra pré-visualização começa com os valores de modelo declarados para ela

Se a entrada de texto funcionar, mas o resultado renderizado não mudar, inspecione a conexão entre o binding do campo e a propriedade lida pelo resultado. Aqui, ambos os caminhos levam a model.title, diretamente ou por meio de displayedTitle. Se alternar a visibilidade apagar o detalhe, procure código que atribua um valor vazio; este exemplo só altera showsDetail.

Nenhum compilador Swift nem ambiente de execução de pré-visualizações do macOS estava disponível no ambiente de pesquisa, então os exemplos foram analisados com base nas APIs documentadas, sem compilação ou execução. Compile o destino e conclua as verificações de interação no Xcode antes de adaptar o editor.

Mantenha a configuração compartilhada separada dos dados de exemplo editáveis

Para um modelo tão pequeno, a construção local facilita a compreensão de cada pré-visualização. Se várias pré-visualizações precisarem de uma configuração reutilizável e custosa, a Apple oferece PreviewModifier: seu contexto compartilhado é armazenado em cache e reutilizado pelas pré-visualizações participantes. A API requer macOS 15 ou posterior. PreviewModifier.

Esse comportamento de compartilhamento documentado leva a uma escolha prática de design: mantenha localmente os modelos de dados de exemplo editáveis de forma independente e reserve o contexto compartilhado para configurações que você queira que as pré-visualizações participantes reutilizem intencionalmente. Um modelo mutável compartilhado também compartilharia suas edições, o que poderia dificultar a comparação entre cenários separados.

Se uma view existente obtiver seu modelo do ambiente pelo tipo, injete a instância necessária na raiz da pré-visualização. A Apple documenta que a ausência de um modelo não opcional do tipo solicitado causa uma exceção. Portanto, a pré-visualização precisa fornecer as dependências que a raiz escolhida realmente lê. Gerenciando os dados do modelo no seu app.

Preserve os limites do AppKit e do TextKit

O editor acima usa controles SwiftUI. Se o editor existente para macOS contiver uma view de texto AppKit, use NSViewRepresentable para integrar essa view à hierarquia do SwiftUI. Crie-a e configure-a por meio de makeNSView e, em seguida, aplique o estado recebido do SwiftUI por meio de updateNSView. Encaminhe as alterações do delegado do AppKit por meio de um coordenador quando as edições precisarem voltar ao SwiftUI. Deixe que o SwiftUI controle o frame e os limites da view representada. NSViewRepresentable.

A Apple também permite pré-visualizar diretamente views e controladores de view do AppKit. No entanto, @Previewable é um recurso exclusivo do SwiftUI e não se aplica a pré-visualizações diretas do AppKit. Para usar o padrão de estado local deste artigo com conteúdo AppKit, pré-visualize um host SwiftUI que contenha o representable. Adicionando pré-visualizações aos arquivos da sua interface.

Preserve a escolha do mecanismo de texto ao construir um NSTextView. A Apple documenta NSTextView(usingTextLayoutManager: true) para escolher o TextKit 2 durante a inicialização. As orientações da Apple sobre TextKit também explicam que acessar layoutManager do TextKit 1 pode acionar uma reversão unidirecional para aquela instância da view de texto. Use as APIs apropriadas do TextKit 2 quando esse for o mecanismo desejado; uma pré-visualização não elimina esses limites. Novidades no TextKit e nas views de texto.

Diagnostique falhas de pré-visualização no limite de propriedade

Comece pelo primeiro diagnóstico de compilação. As macros Swift geram código em tempo de compilação, então um erro destacado em uma chamada de macro pode envolver declarações geradas. O comando Editor > Expand Macro do Xcode permite inspecionar esse código. Aplicando macros.

Em seguida, verifique o mecanismo de estado. Um ObservableObject existente baseado em Combine precisa do padrão de propriedade correspondente: a Apple alerta que armazenar esse tipo de objeto em State não acompanha alterações em suas propriedades publicadas e orienta os proprietários a usar StateObject. O exemplo aqui usa @Observable, portanto a propriedade do estado segue o caminho de Observation. State.

Mantenha o arquivo final de pré-visualização centrado em valores iniciais explícitos e interações visíveis. Quando os cenários padrão, de título longo e de título vazio funcionarem como esperado, reutilize o mesmo editor com um modelo pertencente à view pai apropriada do seu app. Os dados de exemplo da pré-visualização continuam sendo uma forma compacta de reproduzir essas condições de interface.

Fontes