Using $ for Binding in function parameter list

I recently found out you can use $ variable names in closure parameters like so:

Bind("Title") { $title in
      TextField(title, text: $title)
}

However it seems that the same is not possible for a function parameters like so:

func foo(title $title: Binding<String>) {
      TextField(title, text: $title)
}

Looking at the swift grammar both of these are identifiers which can be property-wrapper-projection -> $ identifier-characters

However the compiler gives an error at the function declaration:

Cannot declare entity named '$title'; the '$' prefix is reserved for implicitly-synthesized declarations

If the $ prefix is reserved only for implicitly-synthesized declarations then how is it possible to use with the closure?

2 Likes

You need to use a property wrapper on the parameter.

func foo(@Binding title: String) {
  TextField(title, text: $title)
}

foo($title: .constant("R.I.P. Taylor Hawkins 🥁"))
1 Like

oh wow, I knew you could use the property wrapper on the parameter, but thought it wasn't possible to pass in a binding then, had no idea about using the $ syntax at the call site.

Even in the SwiftUI module itself this isn't used, eg TextField init is defined as:

public init(_ titleKey: LocalizedStringKey, text: Binding<String>, axis: Axis)

It feels like using the dollar syntax in the function definition would be better, as then the caller doesn't need to know this, as even if the init function above was defined with the property wrapper on the parameter, then caller would need to know to use the dollar syntax at the call site. Also it would make it easy to accidentally pass in the String.

eg

@Binding
var text: String

foo(title: text) // Oops the string has been passed in as a constant

So I guess there's no way to use the nicer syntax in the function declaration without affecting the caller :/

No, that's impossible, because Binding doesn't have an initializer that only takes wrappedValue.
(You can try doing it, but the code you posted will crash the 5.8 compiler.)

What would you like to do with it? I can't tell what your goals are.
To me, it seems like the entire point of the feature was to enable nested Bindings with ForEach, which was sorely lacking in the first iteration of SwiftUI.