@Binding — vad är det, hur fungerar det och exempel i SwiftUI

Författare: IT Sectr Publicerad: 2026-06-19 Lästid: 7 min

@Binding är en Property Wrapper i SwiftUI som skapar en referens till data som ägs av en annan komponent. Binding lagrar inte värdet självständigt — det ger bara tillgång till den befintliga sanningskällan genom $-projektionen. Enligt Apple Developer Documentation (2025) tillhandahåller Binding en reaktiv tvåvägsförbindelse mellan förälder- och barnvyn utan direkt ägande av data. @Binding är den viktigaste mekanismen för att skicka föränderligt tillstånd nedåt i hierarkin.

Huvudpunkter

  • @Binding — Property Wrapper för att skapa en referens till föräldervyns tillstånd
  • Utan ägande — Binding lagrar inte data, ger bara tillgång till sanningskällan
  • $-projektion — $stateValue skapar Binding från @State eller @StateObject
  • Tvåvägsförbindelse — ändringar i barnvyn återspeglas omedelbart i föräldern
  • Binding.constant — fast värde för prototypframställning utan återkoppling

Vad är @Binding i SwiftUI?

@Binding är en Property Wrapper som skapar en tvåvägsförbindelse mellan en egenskap lagrad i föräldervyn och en barnkomponent. Huvudskillnaden mellan Binding och @State: Binding äger inte data. Det läser och skriver bara värdet via den verkliga källan — @State, @StateObject eller en annan Binding i föräldern. Utan Binding skulle barnvyn inte kunna ändra förfaderns tillstånd utan callbacks eller delegater.

Binding är implementerad som en struktur med två egenskaper: wrappedValue (aktuellt värde) och projectedValue (själva Binding, tillgängligt via $). När barnvyn ändrar wrappedValue via Binding, överför SwiftUI ändringen till datakällan och ritar om alla beroende vyer. Detta sker synkront inom den aktuella uppdateringscykeln.

Viktig egenskap: @Binding är inte begränsad till en nivås överföring. Binding kan skickas genom flera nivåer av hierarkin — varje barnkomponent får en referens till samma datakälla. En ändring på vilken nivå som helst orsakar en enhetlig uppdatering av alla länkade vyer.

Hur fungerar tvåvägsförbindelsen Binding

Mekanismen för tvåvägsförbindelse via @Binding bygger på projektion av Property Wrappers. När föräldern deklarerar @State var value: T, genererar SwiftUI automatiskt projektionen $value av typen Binding. Genom att skicka $value till en barnkomponent med @Binding var value: T kopplar du båda vyerna till en minnescell. Varje skrivning via Binding i barnvyn orsakar omritning av båda komponenterna.

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

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

struct SliderView: View {
    @Binding var value: Double

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

I exemplet äger SliderContainer @State value, och SliderView får Binding via $value. Reglaget inuti SliderView är kopplat till denna Binding. När reglaget dras ändrar Slider värdet via Binding, vilket automatiskt uppdaterar @State i SliderContainer, och båda vyerna visar det aktuella numret. Hela kedjan fungerar utan en enda callback eller notifiering.

För att skapa Binding från @StateObject eller @ObservedObject används samma projektion: $object.property ger Binding. Detta gör det möjligt att skicka enskilda egenskaper hos ObservableObject till barnvyer utan att skicka hela objektet. Ett sådant tillvägagångssätt ger en snävare bindning och förhindrar onödiga omritningar.

@Binding vs callbacks: vad ska man välja

Före SwiftUI var standardsättet att skicka ändringar uppåt i hierarkin via callbacks och delegater: föräldern skickade en closure, barnkomponenten anropade den vid ändring. @Binding erbjuder ett alternativ med mindre kod och mer deklarativ syntax. Istället för att skicka en slutförandeclosure räcker det att skicka $stateValue.

Kriterium@BindingCallbacks
KodEn anteckning + $Closure + anrop
FlernivåAutomatiskKedja av closures
TestningBinding(value:constant)Mock-closures
LäsbarhetHögMedel
FlexibilitetEndast dataVilken logik som helst

Använd @Binding när barnvyn bara behöver läsa och ändra värdet. Om sidoeffekter krävs vid ändring (validering, loggning, nätverksförfrågan), kombinera Binding med en callback: skicka Binding för data och closure för händelser. Till exempel kan TextField kopplas till Binding, och onChange startar valideringen.

Användningsmönster för @Binding i projekt

@Binding tillämpas i flera typiska scenarier. Första — anpassade kontroller: strömbrytare, reglage, färgväljare och andra interaktiva element tar emot Binding för tvåvägssynkronisering. Andra — modala fönster: visningsflaggan för sheet skickas som Binding, vilket gör att barnvyn kan stänga sig själv via presentationMode eller direkt inställning.

Tredje mönstret — formulär med uppdelning. Om ett formulär består av många fält kan varje fält extraheras till en separat komponent som tar emot Binding för sitt värde. Detta förenklar testning och återanvändning av fält mellan olika formulär. Förälderkomponenten förblir den enda ägaren av hela formulärmodellen.

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

Komponenten FormField tar emot en etikett och en Binding till en sträng. Den visar en rubrik och ett TextField kopplat till den skickade Binding. Vilket formulär som helst kan använda FormField flera gånger genom att skicka $property för varje fält. Detta minskar duplicering av märkspråk och centraliserar stilsättningen av textfält.

Skapa anpassade Binding

SwiftUI tillåter manuell skapande av Binding via initialiseraren Binding(get:set:). Detta är användbart när logik behöver läggas till vid läsning eller skrivning av värdet. Du kan till exempel skapa en Binding som formaterar ett tal före lagring, eller en Binding som synkroniserar värdet med en fjärrserver vid varje ändring.

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

I listningen konverterar anpassad emailBinding automatiskt text till gemener och tar bort mellanslag vid varje ändring. TextField använder denna Binding istället för direkt koppling till $email. Ett sådant tillvägagångssätt gör det möjligt att centralisera validering och datatransformation inom Binding, utan att förorena koden med onChange-hanterare.

Fel och antimönster med @Binding

Det första och vanligaste felet — att skicka värdet istället för Binding. Om en barnkomponent deklarerar @Binding var text: String och föräldern skickar text (utan $), ger kompilatorn ett fel: Cannot convert value of type 'String' to expected argument type 'Binding'. Lösning — använd alltid $-prefixet vid överföring: $text.

Andra felet — Binding på skrivskyddade data. Om barnvyn bara behöver läsa värdet, använd inte @Binding — en vanlig let eller @State från föräldern räcker. Binding innebär skrivmöjlighet och extra ändringsrättigheter försvårar felsökning och bryter mot principen om minimala privilegier.

Tredje problemet — Binding.constant i produktion. Binding.constant(value) skapar en falsk bindning utan återkoppling — ändringar ignoreras. Använd constant endast för prototypframställning och förhandsvisningar (Xcode Previews), men aldrig i verklig kod. För tester, använd Binding(get:set:) med kontrollerat beteende.

Vanliga frågor

Vad är skillnaden mellan @Binding och @State?

@State äger data och hanterar deras lagring på heapen. @Binding refererar bara till befintligt tillstånd utan ägande. @State är alltid private, @Binding — ingångsparameter för barnvyn.

Kan man skapa en Binding utan @State?

Ja, via initialiseraren Binding(get:set:) eller Binding.constant(value). Binding kan också erhållas från @StateObject via projektionen $object.$property och från Publisher via Binding(get:set:) inuti Subscribe.

Hur skickar man Binding genom flera nivåer av nästling?

@Binding skickas i en kedja: varje mellanliggande komponent deklarerar @Binding och skickar det vidare via $. Alla nivåer refererar till en datakälla i rotvyn.

Varför uppdaterar inte Binding.constant gränssnittet?

Binding.constant skapar ett tyst omslag — settern ignorerar nya värden. Det är endast avsett för prototypframställning och SwiftUI Previews, där återkoppling från barnkomponenten inte behövs.

Kan @Binding vara valfri?

Ja, Binding<T?> stöds. Om du skickar Binding<String?>, kan barnvyn sätta nil. Detta är praktiskt för valfria formulärfält eller tillstånd med återställningsmöjlighet.

Sammanfattning

  • @Binding — Property Wrapper för tvåvägsförbindelse med föräldervyns data
  • Äger inte data — ger bara tillgång till sanningskällan
  • $-projektion omvandlar @State, @StateObject till Binding för överföring till barnvyer
  • Anpassad Binding skapas via Binding(get:set:) med extra logik
  • Binding.constant — endast för förhandsvisningar och prototyper
  • Flernivåöverföring — Binding går genom vilket nästlingsdjup som helst
  • Alternativ till callbacks — deklarativt sätt att ändra tillstånd från barnkomponenter

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också