Understanding @Binding in SwiftUI

When I first started building SwiftUI apps, I was constantly running into situations where I needed different parts of my interface to talk to each other. That’s when I discovered @Binding, and honestly, it was a game-changer for how I think about data flow in my apps.

What @Binding Really Means to Me

I like to think of @Binding as creating a direct line of communication between my views and the data they need to work with. It’s not storing the data itself – instead, it’s like having a remote control that lets me read and change data that lives somewhere else in my app.

The way I explain it to myself: if @State is like owning a book, then @Binding is like borrowing someone’s book with permission to write notes in it.

Here’s how I typically set this up:

struct ParentView: View {
    @State private var userName = ""
    
    var body: some View {
        VStack {
            Text("Hello, \(userName)!")
            UserInputForm(userName: $userName)
        }
    }
}

struct UserInputForm: View {
    @Binding var userName: String
    
    var body: some View {
        TextField("Enter your name", text: $userName)
    }
}
How I Use the Two-Way Connection

The $ symbol is something I use constantly now. When I have a @State property, putting that dollar sign in front creates a binding that I can pass around to other views or UI components.

What I love about this setup is that it truly works both ways:

  • When someone types in the TextField, my original userName variable gets updated automatically
  • If I change userName programmatically somewhere else, the TextField immediately shows the new value
The UI Components I Work With Most

Through my SwiftUI projects, I’ve found myself using bindings with these components all the time:

  • TextField – for any text input where I need to capture what users type
  • Toggle – perfect for settings screens and on/off switches
  • Slider – great for volume controls or any numeric input
  • Picker – whenever I need users to select from a list of options
  • DatePicker – essential for any app dealing with scheduling or events
How I Decide Between @State and @Binding

Over time, I’ve developed a mental checklist:

I reach for @State when:

  • The data belongs to just one view
  • I’m dealing with temporary UI state like whether a sheet is showing
  • The data doesn’t need to be shared with other parts of my app

I use @Binding when:

  • A child view needs to modify data that lives in a parent view
  • I’m building reusable components that work with external data
  • I want to keep one authoritative source for my data while letting multiple views interact with it

Sometimes the built-in binding behavior isn’t quite what I need. I’ve gotten comfortable creating custom bindings when I need special logic:

Lessons I’ve Learned the Hard Way

@Binding works best when:

  • I keep my data hierarchy relatively flat passing bindings through too many view levels gets confusing fast
  • I’m clear about which view “owns” the data and which views are just borrowing it
  • I remember that the binding is only as good as the data source it points to

Things that tripped me up initially:

  • Forgetting that if the source data goes away, my binding becomes invalid
  • Overusing bindings when simple value passing would work better
  • Not realizing how much easier debugging becomes when I have clear data ownership
What’s Coming Next

With the newer @Observable and @Bindable features in recent iOS versions, I’m finding even more elegant ways to handle complex data relationships. But the core concept of @Binding – creating that two-way street between my UI and my data – remains fundamental to how I build SwiftUI apps.

The thing I appreciate most about @Binding is how it makes my code feel more predictable. I know exactly where my data lives, which views can change it, and I never have to worry about keeping different parts of my UI in sync manually.