@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 é 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.
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.
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.
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 | @Binding | Callbacks |
|---|---|---|
| Código | Uma anotação + $ | Closure + invocação |
| Multinível | Automático | Cadeia de closures |
| Teste | Binding(value:constant) | Closures mock |
| Legibilidade | Alta | Média |
| Flexibilidade | Apenas dados | Qualquer 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.
@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.
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.
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.
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.
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
@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.
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.
@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.
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.
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
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.
Leia também