@Binding — ce este, cum funcționează și exemple în SwiftUI

Autor: IT Sectr Publicat: 2026-06-19 Timp de citire: 7 min

@Binding este un Property Wrapper în SwiftUI care creează o referință la datele deținute de o altă componentă. Binding nu stochează valoarea independent — oferă doar acces la sursa existentă de adevăr prin proiecția $. Conform Apple Developer Documentation (2025), Binding asigură o legătură bidirecțională reactivă între vederea părinte și cea copil fără posesia directă a datelor. @Binding este mecanismul cheie pentru transmiterea stării modificabile în josul ierarhiei.

Principalele puncte

  • @Binding — Property Wrapper pentru crearea unei referințe la starea vederii părinte
  • Fără posesie — Binding nu stochează date, ci doar oferă acces la sursa de adevăr
  • Proiecția $ — $stateValue creează Binding din @State sau @StateObject
  • Legătură bidirecțională — modificările în vederea copil se reflectă imediat în părinte
  • Binding.constant — valoare fixă pentru prototipare fără feedback

Ce este @Binding în SwiftUI?

@Binding este un Property Wrapper care creează o legătură bidirecțională între o proprietate stocată în vederea părinte și o componentă copil. Diferența principală dintre Binding și @State: Binding nu deține datele. El doar citește și scrie valoarea prin sursa reală — @State, @StateObject sau un alt Binding din părinte. Fără Binding, vederile copil nu ar putea modifica starea strămoșului fără callbackuri sau delegați.

Binding este implementat ca o structură cu două proprietăți: wrappedValue (valoarea curentă) și projectedValue (Bindingul însuși, accesibil prin $). Când vederea copil modifică wrappedValue prin Binding, SwiftUI transmite schimbarea la sursa de date și redesenează toate vederile dependente. Aceasta se întâmplă sincron în cadrul ciclului curent de actualizare.

Caracteristică importantă: @Binding nu se limitează la transmiterea pe un singur nivel. Binding poate fi transmis prin mai multe niveluri ale ierarhiei — fiecare componentă copil primește o referință la aceeași sursă de date. Modificarea la orice nivel cauzează o actualizare unitară a tuturor vederilor legate.

Cum funcționează legătura bidirecțională Binding

Mecanismul legăturii bidirecționale prin @Binding se bazează pe proiecția Property Wrapperurilor. Când părintele declară @State var value: T, SwiftUI generează automat proiecția $value de tip Binding. Transmițând $value către o componentă copil cu @Binding var value: T, conectezi ambele vederi la o singură celulă de memorie. Orice scriere prin Binding în vederea copil cauzează redesenarea ambelor componente.

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

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

struct SliderView: View {
    @Binding var value: Double

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

În exemplu, SliderContainer deține @State value, iar SliderView primește Binding prin $value. Sliderul din interiorul SliderView este legat de acest Binding. La tragerea cursorului, Sliderul modifică valoarea prin Binding, ceea ce actualizează automat @State în SliderContainer și ambele vederi afișează numărul curent. Întregul lanț funcționează fără niciun callback sau notificare.

Pentru a crea Binding din @StateObject sau @ObservedObject se folosește aceeași proiecție: $object.property dă Binding. Aceasta permite transmiterea proprietăților individuale ale ObservableObject către vederile copil fără a transmite întregul obiect. O astfel de abordare oferă o legătură mai strictă și previne redesenele inutile.

@Binding vs callbackuri: ce să alegi

Înainte de SwiftUI, modul standard de a transmite schimbările în susul ierarhiei era prin callbackuri și delegați: părintele transmitea un closure, componenta copil îl apela la modificare. @Binding oferă o alternativă cu mai puțin cod și o sintaxă mai declarativă. În loc să transmiți un closure de completare, este suficient să transmiți $stateValue.

Criteriu@BindingCallbackuri
CodO adnotare + $Closure + apel
Multi-nivelAutomatLanț de closureuri
TestareBinding(value:constant)Mock-closureuri
LizibilitateRidicatăMedie
FlexibilitateDoar dateOrice logică

Folosește @Binding când vederea copil are nevoie doar să citească și să modifice valoarea. Dacă sunt necesare acțiuni secundare la modificare (validare, logare, cerere de rețea), combină Binding cu un callback: transmite Binding pentru date și closure pentru evenimente. De exemplu, TextField se poate lega la Binding, iar onChange va porni validarea.

Modele de utilizare @Binding în proiecte

@Binding se aplică în câteva scenarii tipice. Primul — controale personalizate: întrerupătoare, glisiere, selectoare de culoare și alte elemente interactive acceptă Binding pentru sincronizare bidirecțională. Al doilea — ferestre modale: indicatorul de afișare sheet este transmis ca Binding, permițând vederii copil să se închidă prin presentationMode sau setare directă.

Al treilea model — formulare cu divizare. Dacă un formular constă din mai multe câmpuri, fiecare câmp poate fi extras într-o componentă separată care acceptă Binding pentru valoarea sa. Aceasta simplifică testarea și reutilizarea câmpurilor între diferite formulare. Componenta părinte rămâne singurul deținător al întregului model al formularului.

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)
        }
    }
}

Componenta FormField primește o etichetă și un Binding la un șir. Afișează o etichetă și un TextField legat de Bindingul transmis. Orice formular poate folosi FormField de mai multe ori, transmițând $property pentru fiecare câmp. Aceasta reduce duplicarea marcajului și centralizează stilizarea câmpurilor text.

Crearea Bindingurilor personalizate

SwiftUI permite crearea manuală a Binding prin inițializatorul Binding(get:set:). Acest lucru este util când trebuie adăugată logică la citirea sau scrierea valorii. De exemplu, poți crea un Binding care formatează un număr înainte de salvare, sau un Binding care sincronizează valoarea cu un server la distanță la fiecare modificare.

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)
    }
}

În listing, emailBinding personalizat convertește automat textul la litere mici și elimină spațiile la fiecare modificare. TextField folosește acest Binding în locul legăturii directe la $email. O astfel de abordare permite centralizarea validării și transformării datelor în interiorul Bindingului, fără a aglomera codul cu handlere onChange.

Erori și antipatternuri cu @Binding

Prima și cea mai răspândită eroare — transmiterea valorii în locul Bindingului. Dacă o componentă copil declară @Binding var text: String, iar părintele transmite text (fără $), compilatorul va da eroarea: Cannot convert value of type 'String' to expected argument type 'Binding'. Soluția — folosește întotdeauna prefixul $ la transmitere: $text.

A doua eroare — Binding pe date read-only. Dacă vederea copil are nevoie doar să citească valoarea, nu folosi @Binding — este suficient un simplu let sau @State din părinte. Binding implică posibilitatea de scriere, iar drepturile suplimentare de modificare complică depanarea și încalcă principiul privilegiilor minime.

A treia problemă — Binding.constant în producție. Binding.constant(value) creează o legătură falsă fără feedback — modificările sunt ignorate. Folosește constant doar pentru prototipare și previzualizări (Xcode Previews), dar niciodată în codul real. Pentru teste, folosește Binding(get:set:) cu comportament controlat.

Întrebări frecvente

Care este diferența dintre @Binding și @State?

@State deține datele și gestionează stocarea lor în heap. @Binding doar face referire la starea existentă fără posesie. @State este întotdeauna private, @Binding — parametru de intrare al vederii copil.

Se poate crea un Binding fără @State?

Da, prin inițializatorul Binding(get:set:) sau Binding.constant(value). De asemenea, Binding poate fi obținut din @StateObject prin proiecția $object.$property și din Publisher prin Binding(get:set:) în interiorul Subscribe.

Cum se transmite Binding prin mai multe niveluri de imbricare?

@Binding se transmite în lanț: fiecare componentă intermediară declară @Binding și îl transmite mai departe prin $. Toate nivelurile fac referire la o singură sursă de date în vederea rădăcină.

De ce Binding.constant nu actualizează interfața?

Binding.constant creează un înveliș mut — setterul ignoră noile valori. Este destinat doar pentru prototipare și SwiftUI Previews, unde nu este necesar feedbackul de la componenta copil.

Poate @Binding să fie opțional?

Da, Binding<T?> este acceptat. Dacă transmiți Binding<String?>, vederea copil poate seta nil. Acest lucru este util pentru câmpuri opționale de formular sau stări cu posibilitatea de resetare.

Rezumat

  • @Binding — Property Wrapper pentru legătura bidirecțională cu datele vederii părinte
  • Nu deține date — doar oferă acces la sursa de adevăr
  • Proiecția $ transformă @State, @StateObject în Binding pentru transmiterea către vederile copil
  • Binding personalizat se creează prin Binding(get:set:) cu logică suplimentară
  • Binding.constant — doar pentru previzualizări și prototipuri
  • Transmitere multi-nivel — Binding trece prin orice adâncime de imbricare
  • Alternativă la callbackuri — mod declarativ de modificare a stării din componentele copil

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și