This tutorial by Apple about SwiftUI uses a dollar sign to bind data, and I‘m having trouble finding more information about this data binding in SwiftUI.
Toggle(isOn: $showFavoritesOnly) {
You use the $ prefix to access a binding to a state variable, or one of its properties.
Is this some sort of inout
type parameter? That uses the ampersand to pass it on.
This is very well explained in WWDC 2019 video 415. You are merely looking at one special case of a broad language feature, namely property wrappers.
A property wrapper (such as @State
) is actually a way of referring to an instance of a type (usually a struct or enum) with the same name (such as State). The latter provides instructions for turning this instance property into a computed property whose getter and setter are the getter and setter for a certain computed property of itself (its wrappedValue
). It also typically holds private storage backing that computed property.
Thus, after the declaration
@State var showFavoritesOnly = true
...showFavoritesOnly
is turned into a computed property, with its getter and setter supplied by the State struct. When you set showFavoritesOnly
to true, that is routed through the State struct's setter and ends up in a stored property of the State instance.
All of this implies that somewhere there is a State instance associated with your showFavoritesOnly
. And there is, but it's hidden from view. Its name, in case you'd like to see that State instance, is _showFavoritesOnly
.
Okay, but when you say $showFavoritesOnly
, you do not get a State struct; you get a Binding struct. Why? That's because a property wrapper has a mechanism for specifying what the returned value from the $
name should be. In the case of State, it specifies that this value should be its own binding
property, which is a Binding (see the docs: https://developer.apple.com/documentation/swiftui/state).
By an amazing coincidence, Toggle's isOn
initializer takes a Binding (again, see the docs, https://developer.apple.com/documentation/swiftui/toggle/3232112-init). You could not have set the Toggle's isOn
to showFavoritesOnly
even if you wanted to! Instead, you set it to the Binding<Bool>
supplied by the State instance, so that the Toggle has automatic two-way communication with the State object. The SwiftUI framework enforces its own correct usage; a Toggle can exist only in relation to some binding that acts as the underlying source of truth for its on/off state. And because it's a binding, not a mere Bool, communication works in both directions: when the user taps the switch in the Toggle, the change in value flows "up" to the State variable by way of the binding.