@Binding — o que é, como funciona e exemplos em SwiftUI

Autor: IT Sectr Publicado: 2026-06-19 Tempo de leitura: 7 min

@Binding é um Property Wrapper no SwiftUI que cria uma referência a dados pertencentes a outro componente. Binding não armazena o valor por si só — ele apenas fornece acesso à fonte de verdade existente através da projeção $. De acordo com a Documentação para Desenvolvedores Apple (2025), o Binding fornece comunicação reativa bidirecional entre a view pai e a filha sem posse direta dos dados. @Binding é o mecanismo chave para passar estado mutável para baixo na hierarquia.

Pontos principais

  • @Binding — Property Wrapper para criar uma referência ao estado da view pai
  • Sem posse — Binding não armazena dados, apenas fornece acesso à fonte de verdade
  • Projeção $ — $stateValue cria um Binding a partir de @State ou @StateObject
  • Vinculação bidirecional — alterações na view filha refletem imediatamente na pai
  • Binding.constant — valor fixo para prototipagem sem feedback

O que é @Binding no SwiftUI?

@Binding é um Property Wrapper que cria uma conexão bidirecional entre uma propriedade armazenada na view pai e um componente filho. A principal diferença entre Binding e @State: Binding não possui os dados. Ele apenas lê e escreve valores através da fonte verdadeira — @State, @StateObject ou outro Binding no pai. Sem Binding, as views filhas não poderiam modificar o estado do ancestral sem callbacks ou delegados.

Binding é implementado como uma estrutura com duas propriedades: wrappedValue (o valor atual) e projectedValue (o próprio Binding, acessível via $). Quando uma view filha altera wrappedValue através do Binding, o SwiftUI transmite a mudança para a fonte de dados e redesenha todas as views dependentes. Isso ocorre sincronamente dentro do ciclo de atualização atual.

Uma característica importante: @Binding não se limita à transmissão de nível único. O Binding pode ser passado através de vários níveis de hierarquia — cada componente filho recebe uma referência à mesma fonte de dados. Uma alteração em qualquer nível desencadeia uma única atualização de todas as views vinculadas.

Como funciona a vinculação bidirecional do Binding

O mecanismo de vinculação bidirecional através de @Binding é construído sobre projeções de Property Wrappers. Quando um pai declara @State var value: T, o SwiftUI gera automaticamente a projeção $value do tipo Binding<T>. Ao passar $value para um componente filho com @Binding var value: T, você conecta ambas as views à mesma célula de memória. Qualquer escrita através do Binding na view filha desencadeia um redesenho de ambos os componentes.

swift
struct SliderContainer: View {
    @State private var value: Double = 0.5

    var body: some View {
        VStack {
            Text("Value: \(value)")
            SliderView(value: $value)
        }
    }
}

struct SliderView: View {
    @Binding var value: Double

    var body: some View {
        Slider(value: $value, in: 0...1)
    }
}

No exemplo, SliderContainer possui @State value, e SliderView recebe o Binding através de $value. O Slider dentro de SliderView está vinculado a este Binding. Ao arrastar o controle deslizante, o Slider altera o valor através do Binding, o que atualiza automaticamente @State no SliderContainer, e ambas as views exibem o número atual. Toda a cadeia funciona sem um único callback ou notificação.

Para criar um Binding a partir de @StateObject ou @ObservedObject, usa-se a mesma projeção: $object.property fornece Binding<PropertyType>. Isso permite passar propriedades individuais de ObservableObject para views filhas sem passar o objeto inteiro. Esta abordagem fornece um acoplamento mais preciso e evita redesenhos desnecessários.

@Binding vs callbacks: o que escolher

Antes do SwiftUI, a maneira padrão de passar alterações para cima na hierarquia era através de callbacks e delegados: o pai passava uma closure, e o componente filho a invocava na alteração. O @Binding oferece uma alternativa com menos código e uma sintaxe mais declarativa. Em vez de passar uma closure de conclusão, você simplesmente passa $stateValue.

Critério@BindingCallbacks
CódigoUma anotação + $Closure + invocação
MultinívelAutomáticoCadeia de closures
TesteBinding(value:constant)Closures mock
LegibilidadeAltaMédia
FlexibilidadeApenas dadosQualquer lógica

Use @Binding quando a view filha precisar apenas ler e modificar um valor. Se efeitos colaterais forem necessários na alteração (validação, registro, requisição de rede), combine Binding com um callback: passe Binding para os dados e uma closure para eventos. Por exemplo, um TextField pode se vincular a um Binding, enquanto o onChange aciona a validação.

Padrões de uso do @Binding em projetos

@Binding é usado em vários cenários típicos. O primeiro — controles personalizados: interruptores, controles deslizantes, seletores de cor e outros elementos interativos aceitam Binding para sincronização bidirecional. O segundo — janelas modais: a flag de exibição da sheet é passada como Binding, permitindo que a view filha se feche através de presentationMode ou definição direta.

O terceiro padrão — formulários com separação. Se um formulário consiste em muitos campos, cada campo pode ser extraído em um componente separado que aceita um Binding para seu valor. Isso simplifica o teste e a reutilização de campos em diferentes formulários. O componente pai permanece o único proprietário de todo o modelo do formulário.

swift
struct FormField: View {
    let title: String
    @Binding var text: String

    var body: some View {
        VStack(alignment: .leading) {
            Text(title).font(.caption)
            TextField("Enter \(title.lowercased())", text: $text)
                .textFieldStyle(.roundedBorder)
        }
    }
}

O componente FormField aceita um título e um Binding para uma string. Ele exibe um rótulo e um TextField vinculado ao Binding passado. Qualquer formulário pode usar FormField várias vezes passando $property para cada campo. Isso reduz a duplicação de marcação e centraliza a estilização dos campos de texto.

Criação de Bindings personalizados

O SwiftUI permite criar Binding manualmente através do inicializador Binding(get:set:). Isso é útil quando é necessário adicionar lógica ao ler ou escrever um valor. Por exemplo, pode-se criar um Binding que formata um número antes de salvar, ou um Binding que sincroniza o valor com um servidor remoto a cada alteração.

swift
struct ValidatedField: View {
    @State private var email: String = ""

    var emailBinding: Binding<String> {
        .init(
            get: { email },
            set: { email = $0.lowercased().trimmingCharacters(in: .whitespaces) }
        )
    }

    var body: some View {
        TextField("Email", text: emailBinding)
    }
}

Na listagem, o emailBinding personalizado converte automaticamente o texto para minúsculas e remove espaços a cada alteração. O TextField usa este Binding em vez de vincular diretamente a $email. Esta abordagem centraliza a validação e transformação de dados dentro do Binding sem poluir o código com manipuladores onChange.

Erros e antipadrões com @Binding

O primeiro e mais comum erro é passar um valor em vez de um Binding. Se um componente filho declara @Binding var text: String, e o pai passa text (sem $), o compilador dará um erro: Cannot convert value of type 'String' to expected argument type 'Binding<String>'. A solução — use sempre o prefixo $ ao passar: $text.

O segundo erro — Binding em dados somente leitura. Se a view filha precisa apenas ler um valor, não use @Binding — basta um let simples ou @State do pai. Binding implica capacidade de escrita, e permissões de modificação excessivas complicam a depuração e violam o princípio do privilégio mínimo.

O terceiro problema — Binding.constant em produção. Binding.constant(value) cria uma vinculação fictícia sem feedback — as alterações são ignoradas. Use constant apenas para prototipagem e pré-visualizações (Xcode Previews), mas nunca em código real. Para testes, use Binding(get:set:) com comportamento controlado.

Perguntas frequentes

Qual é a diferença entre @Binding e @State?

@State possui os dados e gerencia seu armazenamento no heap. @Binding apenas referencia o estado existente sem posse. @State é sempre privado, @Binding é um parâmetro de entrada da view filha.

Pode-se criar um Binding sem @State?

Sim, através do inicializador Binding(get:set:) ou Binding.constant(value). Binding também pode ser obtido de @StateObject através da projeção $object.$property e de Publisher através de Binding(get:set:) dentro de Subscribe.

Como passar Binding através de múltiplos níveis de aninhamento?

@Binding é passado por cadeia: cada componente intermediário declara @Binding e o passa adiante através de $. Todos os níveis referenciam a mesma fonte de dados na view raiz.

Por que Binding.constant não atualiza a interface?

Binding.constant cria um invólucro mudo — o setter ignora novos valores. Ele é destinado apenas para prototipagem e Previews do SwiftUI onde o feedback do componente filho não é necessário.

@Binding pode ser opcional?

Sim, Binding<T?> é suportado. Se você passar Binding<String?>, a view filha poderá definir nil. Isso é conveniente para campos de formulário opcionais ou estados com possibilidade de reinicialização.

Resumo

  • @Binding — Property Wrapper para vinculação bidirecional com dados da view pai
  • Não possui dados — apenas fornece acesso à fonte de verdade
  • Projeção $ converte @State, @StateObject em Binding para passar a views filhas
  • Binding personalizado criado via Binding(get:set:) com lógica adicional
  • Binding.constant — apenas para pré-visualizações e protótipos
  • Transmissão multinível — Binding atravessa qualquer profundidade de aninhamento
  • Alternativa a callbacks — forma declarativa de modificar o estado a partir de componentes filhos

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também