19

I watched some WWDC videos and Apple docs about data binding, and according to my current understanding, @State as a property delegate will provide a binding connection between the view and the annotated property, for example:

@State var myText: String

var body: some View {
  VStack {
    TextField($myText, placeholder: Text("input"))
    Text(myText)
  }
}

This will bind myText with the content of the text field I added (i.e. one changes the other will follows up to update)

However, though I know $myText refers to the binding type of Binding, I noticed that Binding is also a property delegate, and I noticed it appears in some code examples from Apple. I have no idea what this is used for as a property delegate. @State already does the binding work, then what do we need @Binding for? Apple docs suck for now about this.

Rafael Chaves
  • 553
  • 4
  • 12
Wizard
  • 389
  • 1
  • 2
  • 12
  • Regarding `@State` keyword you can [read this](https://stackoverflow.com/questions/56438730/what-does-the-swiftui-state-keyword-do). – TheTiger Jun 07 '19 at 06:50

5 Answers5

17

According to this WWDC Talk (Data Flow through Swift UI):

https://developer.apple.com/wwdc19/226

@State should be used for local/private changes inside a View. Ideally, they would be private.

@Binding should be used in subviews/reusable components when the value lives outside the current view domain.

You can see it in presentation(:_) APIs.

There are probably bunch of states inside them, that tell SwiftUI how to display them - but the decision of whether it should appear or not it's up to the superview, hence the @Binding (isShowing) you need to provide.

Matteo Pacini
  • 21,796
  • 7
  • 67
  • 74
11

@State is just another @propertyWrapper that outlines a source of truth.

"... When you use state the framework allocate persistence storage for variable and tracks it as a dependency ... you alway has to specify an initial constant value" - WWDC19 Session 226(07:41)

@Binding yet another @propertyWrapper that depends explicitly on state.

"... By using the Binding property wrapper you define an explicit dependency to a source of truth without owning it, additionally you don't need to specify an initial value because binding can be derived from state." - WWDC19 Session 226 (13:01)

enter image description here - WWDC19 Session 226

Cjay
  • 1,093
  • 6
  • 11
5
  • If you need a simple property that belongs to a single view you should use @State
  • If you need to have complex property that may belong to several view(like 2-3 views) you shall use @ObjectBinding
  • Lastly, if you need to have property that needs to use all around views you shall use @EnvironmentObject.
atalayasa
  • 3,310
  • 25
  • 42
4

Binding<T> is the property delegate of @Binding.

$myText gives you a Binding<String>.

The way that @State "does binding work" as you described it, is to give you a Binding<String> initialized with a getter/setter that captures reference of an instance of State<T>.

Now TextField mutates the value of myText by calling the setter of the pass-in binding, which in turn calls the setter of State<T> that actually sets myText.

As you can see, binding does not need to have the actual stored property, it delegates to some other instance that does have the storage, which in this case is @State. Hence the name.

Jim lai
  • 1,224
  • 8
  • 12
3

@State already does the binding work, then what do we need @Binding for

@State doesn't create the binding by yourself. It has a public var binding: Binding<Value> property that (docs):

Use a binding to create a two-way connection between a view and its underlying model.

(in your case between String and TextField)

So, the binding states for bind value back and forth and the @State using for reading and mutating the value and it provides the binding on the value it stores.

pacification
  • 5,838
  • 4
  • 29
  • 51